@@ -2277,10 +2277,14 @@ struct OptimizeInstructions
2277
2277
// emit a null check.
2278
2278
bool needsNullCheck = ref->type .getNullability () == Nullable &&
2279
2279
curr->type .getNullability () == NonNullable;
2280
+ // Same with exactness.
2281
+ bool needsExactCast = ref->type .getExactness () == Inexact &&
2282
+ curr->type .getExactness () == Exact;
2280
2283
// If the best value to propagate is the argument to the cast, we can
2281
2284
// simply remove the cast (or downgrade it to a null check if
2282
- // necessary).
2283
- if (ref == curr->ref ) {
2285
+ // necessary). This does not work if we need a cast to prove
2286
+ // exactness.
2287
+ if (ref == curr->ref && !needsExactCast) {
2284
2288
if (needsNullCheck) {
2285
2289
replaceCurrent (builder.makeRefAs (RefAsNonNull, curr->ref ));
2286
2290
} else {
@@ -2289,17 +2293,22 @@ struct OptimizeInstructions
2289
2293
return ;
2290
2294
}
2291
2295
// Otherwise we can't just remove the cast and replace it with `ref`
2292
- // because the intermediate expressions might have had side effects.
2293
- // We can replace the cast with a drop followed by a direct return of
2294
- // the value, though.
2296
+ // because the intermediate expressions might have had side effects or
2297
+ // we need to check exactness. We can replace the cast with a drop
2298
+ // followed by a direct return of the value, though.
2295
2299
if (ref->type .isNull ()) {
2300
+ // TODO: Remove this once we type ref.null as exact.
2301
+ if (needsExactCast) {
2302
+ return ;
2303
+ }
2304
+
2296
2305
// We can materialize the resulting null value directly.
2297
2306
//
2298
2307
// The type must be nullable for us to do that, which it normally
2299
2308
// would be, aside from the interesting corner case of
2300
2309
// uninhabitable types:
2301
2310
//
2302
- // (ref.cast func
2311
+ // (ref.cast (ref func)
2303
2312
// (block (result (ref nofunc))
2304
2313
// (unreachable)
2305
2314
// )
0 commit comments