Casting null #152
Description
Currently, ref.cast
is spec'd to trap on null, and always return a non-null reference. For some languages, e.g. Java, casts of a null succeed. Thus to implement this behavior, user code must insert a branch checking for null first. To avoid making that check for null redundant with the null check in ref.cast
, br_on_null
is a natural fit, since it refines the type to be non-null in the fallthrough. But br_on_null
pops the null value off of the operand stack, so we end up with a sequence like:
(block $l1 (ref $t2))
(block $l2)
(br_on_null $l2 x)
(ref_cast $t1 $t2) // <-- benefits from knowing x non-null
(br $l1)
(end)
(ref_null $t2)
(end)
Or another option:
(ref_is_null x)
(if (ref $t2))
(ref_null $t2)
(else)
(ref_cast $t1 $t2 x) // <-- x not known to be non-null here
(end)
(note the above are simplified, omitting the RTT values)
Instead both of these sequences could be simplified if we change the semantics of ref_cast
. For example, if ref_cast
has a type immediate that is allowed to be a nullable type, then the nullability could be used to indicate whether null
is allowed to succeed, or should trap.