@@ -890,17 +890,28 @@ struct Struct2Local : PostWalker<Struct2Local> {
890
890
}
891
891
} else {
892
892
assert (allocIsCastRef);
893
- // The cast succeeds iff the optimized allocation's descriptor is the
894
- // same as the given descriptor and traps otherwise.
895
- auto type = allocation->desc ->type ;
896
- replaceCurrent (builder.blockify (
897
- builder.makeDrop (curr->ref ),
898
- builder.makeIf (
899
- builder.makeRefEq (
900
- curr->desc ,
901
- builder.makeLocalGet (localIndexes[fields.size ()], type)),
902
- builder.makeRefNull (allocation->type .getHeapType ()),
903
- builder.makeUnreachable ())));
893
+ if (!Type::isSubType (allocation->type , curr->type )) {
894
+ // The cast fails, so it must trap. We mark such failing casts as
895
+ // fully consuming their inputs, so we cannot just emit the explicit
896
+ // descriptor equality check below because it would appear to be able
897
+ // to propagate the optimized allocation on to the parent (as a null
898
+ // value, which might not validate).
899
+ replaceCurrent (builder.blockify (builder.makeDrop (curr->ref ),
900
+ builder.makeDrop (curr->desc ),
901
+ builder.makeUnreachable ()));
902
+ } else {
903
+ // The cast succeeds iff the optimized allocation's descriptor is the
904
+ // same as the given descriptor and traps otherwise.
905
+ auto type = allocation->desc ->type ;
906
+ replaceCurrent (builder.blockify (
907
+ builder.makeDrop (curr->ref ),
908
+ builder.makeIf (
909
+ builder.makeRefEq (
910
+ curr->desc ,
911
+ builder.makeLocalGet (localIndexes[fields.size ()], type)),
912
+ builder.makeRefNull (allocation->type .getHeapType ()),
913
+ builder.makeUnreachable ())));
914
+ }
904
915
}
905
916
} else {
906
917
// We know this RefCast receives our allocation, so we can see whether it
0 commit comments