Closed eriksoe closed 14 years ago
Urgh; this is pretty bad. I was hoping that the surrounding logic (eg BEAM code checking conditions for a record update operation) would ensure the proper conditions.
That error should also cause a verifier error; I have not seen such ones for this case. But perhaps another erlc generates such patterns.
Oops, in this instruction sequence from error_handler:check_inheritance/2
; {x,1}
is a tuple, but it is established by means of BIFs, not instructions. The last instruction gets tuple element 1, but X1 is only known to contain whatever is in the head of {x,0}
{get_list,{x,0},{x,1},{x,2}}.
{bif,tuple_size,{f,31},[{x,1}],{x,3}}.
{bif,element,{f,31},[{integer,1},{x,1}],{x,4}}.
{bif,element,{f,31},[{integer,2},{x,1}],{x,5}}.
{bif,tuple_size,{f,31},[{x,5}],{x,6}}.
{get_tuple_element,{x,1},1,{x,7}}.
So in this case, we will have to encode that get_tuple_element
instruction as a call to erlang:element/2
. Somehow erlc
must know that the instruction will not fail (and it is clear to see why), but we don't really have machinery to establish the same integrity assertion.
I suspect the lack of a verifier error is due to fields being resolved lazily... a bit of a surprise there.
I fixed the compiler, so that if type inference cannot establish that the argument to get_tuple_element is a tuple, I insert a cast. So I am closing this.
CompilerVisitor generates such code for get_tuple_element when the argument is not statically known to be a tuple.
Modules for which such generated code has been seen: error_handler and yeccparser. The assertion assert(val.type.getInternalName().startsWith("erjang/ETuple")); is triggered if inserted in the get_tuple_element case in CompilerVisitor.
(When fixing this, please also ensure that things also go right if get_tuple_element is used to extract element N from something which is statically only known to be a tuple of size M where M<N.)