diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/type-updating.h | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/src/ir/type-updating.h b/src/ir/type-updating.h index d224f93dc..160934da1 100644 --- a/src/ir/type-updating.h +++ b/src/ir/type-updating.h @@ -248,14 +248,22 @@ struct TypeUpdater return; // did not turn } } else if (auto* iff = curr->dynCast<If>()) { - // may not be unreachable if just one side is + // We only want to change a concrete type to unreachable here, so undo + // anything else. Other changes can be a problem, like refining the type + // of an if for GC-using code, as the code all around us only assumes we + // are propagating unreachability and not doing a full refinalize. + auto old = iff->type; iff->finalize(); if (curr->type != Type::unreachable) { + iff->type = old; return; // did not turn } } else if (auto* tryy = curr->dynCast<Try>()) { + // See comment on If, above. + auto old = tryy->type; tryy->finalize(); if (curr->type != Type::unreachable) { + tryy->type = old; return; // did not turn } } else { @@ -303,9 +311,13 @@ struct TypeUpdater if (!curr->type.isConcrete()) { return; // nothing concrete to change to unreachable } + // See comment in propagateTypesUp() for If regarding restoring the type. + auto old = curr->type; curr->finalize(); if (curr->type == Type::unreachable) { propagateTypesUp(curr); + } else { + curr->type = old; } } @@ -313,9 +325,13 @@ struct TypeUpdater if (!curr->type.isConcrete()) { return; // nothing concrete to change to unreachable } + // See comment in propagateTypesUp() for Try regarding restoring the type. + auto old = curr->type; curr->finalize(); if (curr->type == Type::unreachable) { propagateTypesUp(curr); + } else { + curr->type = old; } } |