@@ -220,6 +220,15 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
220220
221221 void visitRefGetDesc (RefGetDesc* curr) {
222222 optimizeRead (curr, curr->ref , StructUtils::DescriptorIndex);
223+
224+ // RefGetDesc has the interesting property that we can write a value into
225+ // the field that cannot be read from it: it is valid to write a null, but
226+ // a null can never be read (it would have trapped on the write). Fix that
227+ // up as needed to not break validation.
228+ if (!Type::isSubType (getCurrent ()->type , curr->type )) {
229+ Builder builder (*getModule ());
230+ replaceCurrent (builder.makeRefAs (RefAsNonNull, getCurrent ()));
231+ }
223232 }
224233
225234 void optimizeRead (Expression* curr,
@@ -485,6 +494,10 @@ struct PCVScanner
485494 Index index,
486495 PossibleConstantValues& info) {
487496 info.note (expr, *getModule ());
497+ // TODO: For descriptors we can ignore nullable values that are written, as
498+ // they trap. That is, if one place writes a null and another writes a
499+ // global, only the global is readable, and we can optimize there -
500+ // the null is not a second value.
488501 }
489502
490503 void noteDefault (Type fieldType,
0 commit comments