Skip to content

Commit 4d5d0a9

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Declare captured variables in patterns in the flow analysis
Part of #49749 Change-Id: If58fa05aceb501fd2d0d9b9e5fff911159d4d144 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/268943 Commit-Queue: Chloe Stefantsova <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 5eb0a65 commit 4d5d0a9

11 files changed

+183
-0
lines changed

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

+1
Original file line numberDiff line numberDiff line change
@@ -3465,6 +3465,7 @@ class BodyBuilder extends StackListenerImpl
34653465
if (pattern != null) {
34663466
for (VariableDeclaration variable in pattern.declaredVariables) {
34673467
declareVariable(variable, scope);
3468+
typeInferrer.assignedVariables.declare(variable);
34683469
}
34693470
}
34703471
}

pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart

+3
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
17611761
this);
17621762

17631763
flowAnalysis.ifStatement_thenBegin(condition, node);
1764+
for (VariableDeclaration variable in node.pattern.declaredVariables) {
1765+
flowAnalysis.declare(variable, true);
1766+
}
17641767
StatementInferenceResult thenResult = inferStatement(node.then);
17651768
Statement then;
17661769
if (thenResult.hasChanged) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
test(dynamic x) {
6+
if (x case [String y]) {
7+
return y;
8+
} else {
9+
return null;
10+
}
11+
}
12+
13+
main() {
14+
expectEquals(test(["one", "two", "three"]), "one");
15+
expectEquals(test([1, 2, 3]), null);
16+
expectEquals(test([true, false]), null);
17+
expectEquals(test([]), null);
18+
}
19+
20+
expectEquals(x, y) {
21+
if (x != y) {
22+
throw "Expected $x to be equal to $y.";
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method test(dynamic x) → dynamic {
6+
final dynamic #t1 = x;
7+
if(#t1 is core::List<dynamic> && #t1{core::List<dynamic>}.{core::List::length}{core::int}.{core::num::>=}(1){(core::num) → core::bool} && (let final dynamic #t2 = #t1{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} in #t2 is core::String)) {
8+
final core::List<dynamic> #t3 = #t1 as{ForDynamic} core::List<dynamic>;
9+
core::String y = #t3.{core::List::[]}(0){(core::int) → dynamic} as{ForDynamic,ForNonNullableByDefault} core::String;
10+
{
11+
return y;
12+
}
13+
}
14+
else {
15+
return null;
16+
}
17+
}
18+
static method main() → dynamic {
19+
self::expectEquals(self::test(<core::String>["one", "two", "three"]), "one");
20+
self::expectEquals(self::test(<core::int>[1, 2, 3]), null);
21+
self::expectEquals(self::test(<core::bool>[true, false]), null);
22+
self::expectEquals(self::test(<dynamic>[]), null);
23+
}
24+
static method expectEquals(dynamic x, dynamic y) → dynamic {
25+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
26+
throw "Expected ${x} to be equal to ${y}.";
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method test(dynamic x) → dynamic {
6+
final dynamic #t1 = x;
7+
if(#t1 is core::List<dynamic> && #t1{core::List<dynamic>}.{core::List::length}{core::int}.{core::num::>=}(1){(core::num) → core::bool} && (let final dynamic #t2 = #t1{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} in #t2 is core::String)) {
8+
final core::List<dynamic> #t3 = #t1 as{ForDynamic} core::List<dynamic>;
9+
core::String y = #t3.{core::List::[]}(0){(core::int) → dynamic} as{ForDynamic,ForNonNullableByDefault} core::String;
10+
{
11+
return y;
12+
}
13+
}
14+
else {
15+
return null;
16+
}
17+
}
18+
static method main() → dynamic {
19+
self::expectEquals(self::test(core::_GrowableList::_literal3<core::String>("one", "two", "three")), "one");
20+
self::expectEquals(self::test(core::_GrowableList::_literal3<core::int>(1, 2, 3)), null);
21+
self::expectEquals(self::test(core::_GrowableList::_literal2<core::bool>(true, false)), null);
22+
self::expectEquals(self::test(core::_GrowableList::•<dynamic>(0)), null);
23+
}
24+
static method expectEquals(dynamic x, dynamic y) → dynamic {
25+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
26+
throw "Expected ${x} to be equal to ${y}.";
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
test(dynamic x) {}
2+
main() {}
3+
expectEquals(x, y) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
expectEquals(x, y) {}
2+
main() {}
3+
test(dynamic x) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method test(dynamic x) → dynamic {
6+
final dynamic #t1 = x;
7+
if(#t1 is core::List<dynamic> && #t1{core::List<dynamic>}.{core::List::length}{core::int}.{core::num::>=}(1){(core::num) → core::bool} && (let final dynamic #t2 = #t1{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} in #t2 is core::String)) {
8+
final core::List<dynamic> #t3 = #t1 as{ForDynamic} core::List<dynamic>;
9+
core::String y = #t3.{core::List::[]}(0){(core::int) → dynamic} as{ForDynamic,ForNonNullableByDefault} core::String;
10+
{
11+
return y;
12+
}
13+
}
14+
else {
15+
return null;
16+
}
17+
}
18+
static method main() → dynamic {
19+
self::expectEquals(self::test(<core::String>["one", "two", "three"]), "one");
20+
self::expectEquals(self::test(<core::int>[1, 2, 3]), null);
21+
self::expectEquals(self::test(<core::bool>[true, false]), null);
22+
self::expectEquals(self::test(<dynamic>[]), null);
23+
}
24+
static method expectEquals(dynamic x, dynamic y) → dynamic {
25+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
26+
throw "Expected ${x} to be equal to ${y}.";
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method test(dynamic x) → dynamic {
6+
final dynamic #t1 = x;
7+
if(#t1 is core::List<dynamic> && #t1{core::List<dynamic>}.{core::List::length}{core::int}.{core::num::>=}(1){(core::num) → core::bool} && (let final dynamic #t2 = #t1{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} in #t2 is core::String)) {
8+
final core::List<dynamic> #t3 = #t1 as{ForDynamic} core::List<dynamic>;
9+
core::String y = #t3.{core::List::[]}(0){(core::int) → dynamic} as{ForDynamic,ForNonNullableByDefault} core::String;
10+
{
11+
return y;
12+
}
13+
}
14+
else {
15+
return null;
16+
}
17+
}
18+
static method main() → dynamic {
19+
self::expectEquals(self::test(<core::String>["one", "two", "three"]), "one");
20+
self::expectEquals(self::test(<core::int>[1, 2, 3]), null);
21+
self::expectEquals(self::test(<core::bool>[true, false]), null);
22+
self::expectEquals(self::test(<dynamic>[]), null);
23+
}
24+
static method expectEquals(dynamic x, dynamic y) → dynamic {
25+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
26+
throw "Expected ${x} to be equal to ${y}.";
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
4+
static method test(dynamic x) → dynamic
5+
;
6+
static method main() → dynamic
7+
;
8+
static method expectEquals(dynamic x, dynamic y) → dynamic
9+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method test(dynamic x) → dynamic {
6+
final dynamic #t1 = x;
7+
if(#t1 is core::List<dynamic> && #t1{core::List<dynamic>}.{core::List::length}{core::int}.{core::num::>=}(1){(core::num) → core::bool} && (let final dynamic #t2 = #t1{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} in #t2 is core::String)) {
8+
final core::List<dynamic> #t3 = #t1 as{ForDynamic} core::List<dynamic>;
9+
core::String y = #t3.{core::List::[]}(0){(core::int) → dynamic} as{ForDynamic,ForNonNullableByDefault} core::String;
10+
{
11+
return y;
12+
}
13+
}
14+
else {
15+
return null;
16+
}
17+
}
18+
static method main() → dynamic {
19+
self::expectEquals(self::test(core::_GrowableList::_literal3<core::String>("one", "two", "three")), "one");
20+
self::expectEquals(self::test(core::_GrowableList::_literal3<core::int>(1, 2, 3)), null);
21+
self::expectEquals(self::test(core::_GrowableList::_literal2<core::bool>(true, false)), null);
22+
self::expectEquals(self::test(core::_GrowableList::•<dynamic>(0)), null);
23+
}
24+
static method expectEquals(dynamic x, dynamic y) → dynamic {
25+
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
26+
throw "Expected ${x} to be equal to ${y}.";
27+
}
28+
}

0 commit comments

Comments
 (0)