Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: pkg/compiler/lib/src/inferrer/inferrer_visitor.dart

Issue 1439603002: Fix a bug in type inference for locals in switch statements. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/compiler/dart2js/type_inference_switch_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library inferrer_visitor; 5 library inferrer_visitor;
6 6
7 import 'dart:collection' show 7 import 'dart:collection' show
8 IterableMixin; 8 IterableMixin;
9 9
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 * ... 599 * ...
600 * } 600 * }
601 * :] 601 * :]
602 * 602 *
603 * where [:this:] is the [LocalsHandler] for the paths through the 603 * where [:this:] is the [LocalsHandler] for the paths through the
604 * labeled statement that do not break out. 604 * labeled statement that do not break out.
605 */ 605 */
606 void mergeAfterBreaks(List<LocalsHandler<T>> handlers, 606 void mergeAfterBreaks(List<LocalsHandler<T>> handlers,
607 {bool keepOwnLocals: true}) { 607 {bool keepOwnLocals: true}) {
608 Node level = locals.block; 608 Node level = locals.block;
609 // Use a separate locals handler to perform the merge in, so that Phi
610 // creation does not invalidate previous type knowledge while we might
611 // still look it up.
612 LocalsHandler merged = new LocalsHandler.from(this, level);
609 Set<Local> seenLocals = new Setlet<Local>(); 613 Set<Local> seenLocals = new Setlet<Local>();
610 // If we want to keep the locals, we first merge [this] into itself to 614 bool allBranchesAbort = true;
Kevin Millikin (Google) 2015/11/11 12:14:52 An extra space has crept in.
herhut 2015/12/10 10:09:11 Done.
611 // create the required Phi nodes.
612 if (keepOwnLocals && !seenReturnOrThrow) {
613 mergeHandler(this, seenLocals);
614 }
615 bool allBranchesAbort = true;
616 // Merge all other handlers. 615 // Merge all other handlers.
617 for (LocalsHandler handler in handlers) { 616 for (LocalsHandler handler in handlers) {
618 allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow; 617 allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow;
619 mergeHandler(handler, seenLocals); 618 merged.mergeHandler(handler, seenLocals);
620 } 619 }
621 // Clean up Phi nodes with single input. 620 // If we want to keep own locals, we merge [seenLocals] from [this] into
622 locals.forEachLocal((Local variable, T type) { 621 // [merged] to update the Phi nodes with original values.
623 if (!seenLocals.contains(variable)) return; 622 if (keepOwnLocals && !seenReturnOrThrow) {
624 T newType = types.simplifyPhi(level, variable, type); 623 for (Local variable in seenLocals) {
625 if (newType != type) { 624 T originalType = locals[variable];
626 locals[variable] = newType; 625 if (originalType != null) {
626 merged.locals[variable] = types.addPhiInput(variable,
627 merged.locals[variable],
628 originalType);
629 }
627 } 630 }
631 }
632 // Clean up Phi nodes with single input and store back result into
633 // actual locals handler.
634 merged.locals.forEachOwnLocal((Local variable, T type) {
635 locals[variable] = types.simplifyPhi(level, variable, type);
628 }); 636 });
629 seenReturnOrThrow = allBranchesAbort && 637 seenReturnOrThrow = allBranchesAbort &&
630 (!keepOwnLocals || seenReturnOrThrow); 638 (!keepOwnLocals || seenReturnOrThrow);
631 } 639 }
632 640
633 /** 641 /**
634 * Merge [other] into this handler. Returns whether a local in this 642 * Merge [other] into this handler. Returns whether a local in this
635 * has changed. If [seen] is not null, we allocate new Phi nodes 643 * has changed. If [seen] is not null, we allocate new Phi nodes
636 * unless the local is already present in the set [seen]. This effectively 644 * unless the local is already present in the set [seen]. This effectively
637 * overwrites the current type knowledge in this handler. 645 * overwrites the current type knowledge in this handler.
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 return type; 1546 return type;
1539 } 1547 }
1540 1548
1541 T visitCascade(Cascade node) { 1549 T visitCascade(Cascade node) {
1542 // Ignore the result of the cascade send and return the type of the cascade 1550 // Ignore the result of the cascade send and return the type of the cascade
1543 // receiver. 1551 // receiver.
1544 visit(node.expression); 1552 visit(node.expression);
1545 return cascadeReceiverStack.removeLast(); 1553 return cascadeReceiverStack.removeLast();
1546 } 1554 }
1547 } 1555 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/type_inference_switch_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698