mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 19:36:42 +00:00
[dart2js] Update switch block local handling to correctly propagate types that fall through the block.
Fixes #52170 Change-Id: I7c473c3101d446eb17433d583bfe266bf6f193d6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298760 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com>
This commit is contained in:
parent
47b7c1f31d
commit
b9c73fdf23
|
@ -2564,12 +2564,12 @@ class LocalState {
|
|||
|
||||
LocalState mergeAfterBreaks(InferrerEngine inferrer, List<LocalState> states,
|
||||
{bool keepOwnLocals = true}) {
|
||||
bool allBranchesAbort = true;
|
||||
bool allBranchesReturnOrThrow = true;
|
||||
for (LocalState state in states) {
|
||||
allBranchesAbort = allBranchesAbort && state.seenReturnOrThrow;
|
||||
allBranchesReturnOrThrow &= state.seenReturnOrThrow;
|
||||
}
|
||||
|
||||
keepOwnLocals = keepOwnLocals && !seenReturnOrThrow;
|
||||
keepOwnLocals &= !seenReturnOrThrow;
|
||||
|
||||
LocalsHandler locals = _locals.mergeAfterBreaks(
|
||||
inferrer,
|
||||
|
@ -2577,7 +2577,7 @@ class LocalState {
|
|||
.where((LocalState state) => !state.seenReturnOrThrow)
|
||||
.map((LocalState state) => state._locals),
|
||||
keepOwnLocals: keepOwnLocals);
|
||||
seenReturnOrThrow = allBranchesAbort && !keepOwnLocals;
|
||||
seenReturnOrThrow = allBranchesReturnOrThrow && !keepOwnLocals;
|
||||
return LocalState.internal(locals, _fields, _tryBlock,
|
||||
seenReturnOrThrow: seenReturnOrThrow,
|
||||
seenBreakOrContinue: seenBreakOrContinue);
|
||||
|
|
|
@ -472,7 +472,7 @@ class LocalsHandler {
|
|||
VariableScope merged = tryBlock != null
|
||||
? VariableScope.tryBlock(tryBlock, parent: _locals)
|
||||
: VariableScope(parent: _locals);
|
||||
Set<Local> seenLocals = Setlet<Local>();
|
||||
Map<Local, int> seenLocals = {};
|
||||
// Merge all other handlers.
|
||||
for (LocalsHandler handler in handlers) {
|
||||
final common = _locals.commonParent(handler._locals);
|
||||
|
@ -491,11 +491,12 @@ class LocalsHandler {
|
|||
final myType = merged[local];
|
||||
if (myType == null) return;
|
||||
TypeInformation newType;
|
||||
if (!seenLocals.contains(local)) {
|
||||
final seenCount =
|
||||
seenLocals.update(local, (v) => v + 1, ifAbsent: () => 1);
|
||||
if (seenCount == 1) {
|
||||
newType = inferrer.types.allocatePhi(
|
||||
merged.tryBlock, local, otherType,
|
||||
isTry: merged.isTry);
|
||||
seenLocals.add(local);
|
||||
} else {
|
||||
newType = inferrer.types.addPhiInput(
|
||||
local, myType as PhiElementTypeInformation, otherType);
|
||||
|
@ -505,17 +506,17 @@ class LocalsHandler {
|
|||
}
|
||||
});
|
||||
}
|
||||
// If we want to keep own locals, we merge [seenLocals] from [this] into
|
||||
// [merged] to update the Phi nodes with original values.
|
||||
if (keepOwnLocals) {
|
||||
for (Local variable in seenLocals) {
|
||||
seenLocals.forEach((variable, seenCount) {
|
||||
// If we want to keep own locals or if some branches do not update a seen
|
||||
// local we merge the original type from [this] into [merged].
|
||||
if (seenCount < handlers.length || keepOwnLocals) {
|
||||
final originalType = _locals[variable];
|
||||
if (originalType != null) {
|
||||
merged[variable] = inferrer.types.addPhiInput(variable,
|
||||
merged[variable] as PhiElementTypeInformation, originalType);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Clean up Phi nodes with single input and store back result into
|
||||
// actual locals handler.
|
||||
merged.forEachLocalUntilScope(merged,
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
/*member: getInt:[exact=JSUInt31]*/
|
||||
int get getInt => 42;
|
||||
|
||||
// TODO(http://dartbug.com/52170): Return type should include int. The return
|
||||
// within the loop can and will be invoked with local = 3.
|
||||
/*member: foo:Value([null|exact=JSString], value: "hello")*/
|
||||
/*member: foo:Union(null, [exact=JSString], [exact=JSUInt31])*/
|
||||
foo() {
|
||||
dynamic local = 3;
|
||||
for (int i = 0;
|
||||
|
|
Loading…
Reference in a new issue