Skip to content

Commit

Permalink
Issue 39667. Use flow analysis in IfElement.
Browse files Browse the repository at this point in the history
Bug: #39667
Change-Id: I4528869a8d39d1b27c0cdf21ab20173bdb0efbc4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127482
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
  • Loading branch information
scheglov authored and commit-bot@chromium.org committed Dec 7, 2019
1 parent c17aff8 commit 52dc769
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

void list_if_notNull_then_else_left(int? x) {
[if (null != x) /*nonNullable*/ x else x];
}

void list_if_notNull_then_else_right(int? x) {
[if (x != null) /*nonNullable*/ x else x];
}

void list_if_notNull_thenExit_left(int? x) {
[if (null != x) throw 42, x];
}

void list_if_notNull_thenExit_right(int? x) {
[if (x != null) throw 42, x];
}

void list_if_null_then_else_left(int? x) {
[if (null == x) x else /*nonNullable*/ x ];
}

void list_if_null_then_else_right(int? x) {
[if (x == null) x else /*nonNullable*/ x ];
}

void list_if_null_thenExit_left(int? x) {
[if (null == x) throw 42, /*nonNullable*/ x];
}

void list_if_null_thenExit_right(int? x) {
[if (x == null) throw 42, /*nonNullable*/ x];
}

map_if_notNull_then_else_left(int? x) {
return {if (null != x) /*nonNullable*/ x: /*nonNullable*/ x else x: x};
}

map_if_notNull_then_else_right(int? x) {
return {if (x != null) /*nonNullable*/ x: /*nonNullable*/ x else x: x};
}

map_if_notNull_thenExit_left(int? x) {
return {if (null != x) throw 42: 0, x: x};
}

map_if_notNull_thenExit_right(int? x) {
return {if (x != null) throw 42: 0, x: x};
}

map_if_null_then_else_left(int? x) {
return {if (null == x) x: x else /*nonNullable*/ x: /*nonNullable*/ x };
}

map_if_null_then_else_right(int? x) {
return {if (x == null) x: x else /*nonNullable*/ x: /*nonNullable*/ x };
}

map_if_null_thenExit_left(int? x) {
return {if (null == x) throw 42: 0, /*nonNullable*/ x: /*nonNullable*/ x };
}

map_if_null_thenExit_right(int? x) {
return {if (x == null) throw 42: 0, /*nonNullable*/ x: /*nonNullable*/ x };
}

set_if_notNull_then_else_left(int? x) {
return {if (null != x) /*nonNullable*/ x else x};
}

set_if_notNull_then_else_right(int? x) {
return {if (x != null) /*nonNullable*/ x else x};
}

set_if_notNull_thenExit_left(int? x) {
return {if (null != x) throw 42, x};
}

set_if_notNull_thenExit_right(int? x) {
return {if (x != null) throw 42, x};
}

set_if_null_then_else_left(int? x) {
return {if (null == x) x else /*nonNullable*/ x };
}

set_if_null_then_else_right(int? x) {
return {if (x == null) x else /*nonNullable*/ x };
}

set_if_null_thenExit_left(int? x) {
return {if (null == x) throw 42, /*nonNullable*/ x};
}

set_if_null_thenExit_right(int? x) {
return {if (x == null) throw 42, /*nonNullable*/ x};
}

class C {
C.constructor_if_then_else(int? x) {
[if (x == null) x else /*nonNullable*/ x ];
}

void method_if_then_else(int? x) {
[if (x == null) x else /*nonNullable*/ x ];
}
}
29 changes: 21 additions & 8 deletions pkg/analyzer/lib/src/generated/resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1625,15 +1625,28 @@ class ResolverVisitor extends ScopedVisitor {
InferenceContext.setType(condition, typeProvider.boolType);
// TODO(scheglov) Do we need these checks for null?
condition?.accept(this);

CollectionElement thenElement = node.thenElement;
_promoteManager.visitIfElement_thenElement(
condition,
thenElement,
() {
thenElement.accept(this);
},
);
node.elseElement?.accept(this);
if (_flowAnalysis != null) {
_flowAnalysis.flow.ifStatement_thenBegin(condition);
thenElement.accept(this);
} else {
_promoteManager.visitIfElement_thenElement(
condition,
thenElement,
() {
thenElement.accept(this);
},
);
}

var elseElement = node.elseElement;
if (elseElement != null) {
_flowAnalysis?.flow?.ifStatement_elseBegin();
elseElement.accept(this);
}

_flowAnalysis?.flow?.ifStatement_end(elseElement != null);

node.accept(elementResolver);
node.accept(typeAnalyzer);
Expand Down
6 changes: 5 additions & 1 deletion pkg/front_end/test/id_tests/nullability_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ main(List<String> args) async {
createUriForFileName: createUriForFileName,
onFailure: onFailure,
runTest: runTestFor(
const NullabilityDataComputer(), [cfeNonNullableOnlyConfig]));
const NullabilityDataComputer(), [cfeNonNullableOnlyConfig]),
skipList: [
// TODO(dmitryas): Run all nullability tests.
'if_element.dart',
]);
}

class NullabilityDataComputer extends DataComputer<String> {
Expand Down

0 comments on commit 52dc769

Please sign in to comment.