Skip to content

Commit c536510

Browse files
[nnbd_migration] polish previous postdominator code
Change-Id: Ic99389d331dfa9495c57c16f166610c7149e7fb9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112648 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Mike Fairhurst <[email protected]>
1 parent 2659262 commit c536510

File tree

3 files changed

+60
-29
lines changed

3 files changed

+60
-29
lines changed

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4661,6 +4661,7 @@ class ForPartsWithDeclarationsImpl extends ForPartsImpl
46614661

46624662
@override
46634663
Token get beginToken => _variableList?.beginToken ?? super.beginToken;
4664+
46644665
@override
46654666
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
46664667
..add(_variableList)

pkg/nnbd_migration/lib/src/edge_builder.dart

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
124124
final _guards = <NullabilityNode>[];
125125

126126
/// The scope of locals (parameters, variables) that are post-dominated by the
127-
/// current node as we walk the AST. We use a [ScopedSet] so that outer
127+
/// current node as we walk the AST. We use a [_ScopedLocalSet] so that outer
128128
/// scopes may track their post-dominators separately from inner scopes.
129129
///
130130
/// Note that this is not guaranteed to be complete. It is used to make hard
@@ -499,36 +499,27 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
499499
DecoratedType visitForStatement(ForStatement node) {
500500
// TODO do special condition handling
501501
// TODO do create true/false guards?
502-
// Create a scope of for new initializers etc, which includes previous
503-
// post-dominators.
504-
_postDominatedLocals.doScoped(
505-
copyCurrent: true,
506-
action: () {
507-
final parts = node.forLoopParts;
508-
if (parts is ForParts) {
509-
if (parts is ForPartsWithDeclarations) {
510-
parts.variables.accept(this);
511-
}
512-
if (parts is ForPartsWithExpression) {
513-
parts.initialization.accept(this);
514-
}
515-
parts.condition.accept(this);
516-
}
517-
if (parts is ForEachParts) {
518-
parts.iterable.accept(this);
519-
}
520-
521-
// The condition may fail/iterable may be empty, so the body does not
522-
// post-dominate the parts, or the outer scope.
523-
_postDominatedLocals.popScope();
524-
_postDominatedLocals.pushScope();
502+
final parts = node.forLoopParts;
503+
if (parts is ForParts) {
504+
if (parts is ForPartsWithDeclarations) {
505+
parts.variables?.accept(this);
506+
} else if (parts is ForPartsWithExpression) {
507+
parts.initialization?.accept(this);
508+
}
509+
parts.condition?.accept(this);
510+
} else if (parts is ForEachParts) {
511+
parts.iterable.accept(this);
512+
}
525513

526-
if (parts is ForParts) {
527-
parts.updaters.accept(this);
528-
}
514+
// The condition may fail/iterable may be empty, so the body gets a new
515+
// post-dominator scope.
516+
_postDominatedLocals.doScoped(action: () {
517+
node.body.accept(this);
529518

530-
node.body.accept(this);
531-
});
519+
if (parts is ForParts) {
520+
parts.updaters.accept(this);
521+
}
522+
});
532523
return null;
533524
}
534525

pkg/nnbd_migration/test/edge_builder_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,17 @@ main() {
14321432
// No assertions; just checking that it doesn't crash.
14331433
}
14341434

1435+
test_forStatement_empty() async {
1436+
await analyze('''
1437+
1438+
void test() {
1439+
for (; ; ) {
1440+
return;
1441+
}
1442+
}
1443+
''');
1444+
}
1445+
14351446
test_function_assignment() async {
14361447
await analyze('''
14371448
class C {
@@ -2626,6 +2637,34 @@ void test(List<C> l, C c1, C c2) {
26262637
assertEdge(decoratedTypeAnnotation('C c3').node, never, hard: false));
26272638
}
26282639

2640+
test_postDominators_forStatement_conditional() async {
2641+
await analyze('''
2642+
2643+
class C {
2644+
void m() {}
2645+
}
2646+
void test(bool b1, C c1, C c2, C c3) {
2647+
for (; b1/*check*/; c2.m()) {
2648+
C c4 = c1;
2649+
c4.m();
2650+
return;
2651+
}
2652+
2653+
c3.m();
2654+
}
2655+
''');
2656+
2657+
//TODO(mfairhurst): enable this check
2658+
//assertNullCheck(checkExpression('b1/*check*/'),
2659+
// assertEdge(decoratedTypeAnnotation('bool b1').node, never, hard: true));
2660+
assertNullCheck(checkExpression('c4.m'),
2661+
assertEdge(decoratedTypeAnnotation('C c4').node, never, hard: true));
2662+
assertNullCheck(checkExpression('c2.m'),
2663+
assertEdge(decoratedTypeAnnotation('C c2').node, never, hard: false));
2664+
assertNullCheck(checkExpression('c3.m'),
2665+
assertEdge(decoratedTypeAnnotation('C c3').node, never, hard: false));
2666+
}
2667+
26292668
test_postDominators_forStatement_unconditional() async {
26302669
await analyze('''
26312670

0 commit comments

Comments
 (0)