Skip to content

Commit d2d00ff

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
authored andcommitted
[cfe] Allow unassigned late local variables
This is a partial fix for http://dartbug.com/40601. It will be followed by a CL disallowing definitely unassigned late local variables. Bug: http://dartbug.com/40601 Change-Id: I2cdf95f8cc1cc6fbbb6a5de8d6fa0aa53c6e477d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135309 Commit-Queue: Dmitry Stefantsov <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 1fbc71d commit d2d00ff

14 files changed

+265
-2
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5488,11 +5488,15 @@ class InferenceVisitor
54885488
if (isUnassigned) {
54895489
inferrer.dataForTesting?.flowAnalysisResult?.unassignedNodes?.add(node);
54905490
if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
5491-
// Synthetic variables aren't checked.
5491+
// Synthetic variables, local functions, and variables with
5492+
// invalid types aren't checked.
5493+
// TODO(dmitryas): Report errors on definitely unassigned late
5494+
// local variables with potentially non-nullable types.
54925495
if (variable.name != null &&
54935496
!variable.isLocalFunction &&
54945497
variable.type is! InvalidType &&
5495-
variable.type.isPotentiallyNonNullable) {
5498+
variable.type.isPotentiallyNonNullable &&
5499+
!variable.isLate) {
54965500
if (inferrer.nnbdStrongMode) {
54975501
return new ExpressionInferenceResult(
54985502
new InvalidType(),
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2020, 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+
// The test checks that it's a compile-time error to read a late local
6+
// variables of a potentially non-nullable type if it is definitely
7+
// unassigned.
8+
9+
abstract class A<T> {
10+
bar(T value) {}
11+
barInt(int value) {}
12+
foo() {
13+
late T value;
14+
late int intValue;
15+
bar(value); // Error.
16+
barInt(intValue); // Error.
17+
}
18+
}
19+
20+
main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
;
8+
method bar(generic-covariant-impl self::A::T% value) → dynamic
9+
;
10+
method barInt(core::int value) → dynamic
11+
;
12+
method foo() → dynamic
13+
;
14+
}
15+
static method main() → dynamic
16+
;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
: super core::Object::•()
8+
;
9+
method bar(generic-covariant-impl self::A::T% value) → dynamic {}
10+
method barInt(core::int value) → dynamic {}
11+
method foo() → dynamic {
12+
late self::A::T% value;
13+
late core::int intValue;
14+
this.{self::A::bar}(value);
15+
this.{self::A::barInt}(intValue);
16+
}
17+
}
18+
static method main() → dynamic {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
: super core::Object::•()
8+
;
9+
method bar(generic-covariant-impl self::A::T% value) → dynamic {}
10+
method barInt(core::int value) → dynamic {}
11+
method foo() → dynamic {
12+
late self::A::T% value;
13+
late core::int intValue;
14+
this.{self::A::bar}(value);
15+
this.{self::A::barInt}(intValue);
16+
}
17+
}
18+
static method main() → dynamic {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
: super core::Object::•()
8+
;
9+
method bar(generic-covariant-impl self::A::T% value) → dynamic {}
10+
method barInt(core::int value) → dynamic {}
11+
method foo() → dynamic {
12+
late self::A::T% value;
13+
late core::int intValue;
14+
this.{self::A::bar}(value);
15+
this.{self::A::barInt}(intValue);
16+
}
17+
}
18+
static method main() → dynamic {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
: super core::Object::•()
8+
;
9+
method bar(generic-covariant-impl self::A::T% value) → dynamic {}
10+
method barInt(core::int value) → dynamic {}
11+
method foo() → dynamic {
12+
late self::A::T% value;
13+
late core::int intValue;
14+
this.{self::A::bar}(value);
15+
this.{self::A::barInt}(intValue);
16+
}
17+
}
18+
static method main() → dynamic {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2020, 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+
// This is a regression test to http://dartbug.com/40601.
6+
7+
abstract class A<T> {
8+
T baz();
9+
bar(T value) {}
10+
barInt(int value) {}
11+
foo() {
12+
late T value;
13+
late int intValue;
14+
// The use of variable "value" below shouldn't be a compile-time
15+
// error because it's late and not definitely unassigned.
16+
var result = () {
17+
bar(value);
18+
barInt(intValue);
19+
};
20+
(() {
21+
value = baz();
22+
intValue = 42;
23+
})();
24+
return result;
25+
}
26+
}
27+
28+
main() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
;
8+
abstract method baz() → self::A::T%;
9+
method bar(generic-covariant-impl self::A::T% value) → dynamic
10+
;
11+
method barInt(core::int value) → dynamic
12+
;
13+
method foo() → dynamic
14+
;
15+
}
16+
static method main() → dynamic
17+
;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class A<T extends core::Object? = dynamic> extends core::Object {
6+
synthetic constructor •() → self::A<self::A::T%>
7+
: super core::Object::•()
8+
;
9+
abstract method baz() → self::A::T%;
10+
method bar(generic-covariant-impl self::A::T% value) → dynamic {}
11+
method barInt(core::int value) → dynamic {}
12+
method foo() → dynamic {
13+
late self::A::T% value;
14+
late core::int intValue;
15+
() → core::Null? result = () → core::Null? {
16+
this.{self::A::bar}(value);
17+
this.{self::A::barInt}(intValue);
18+
};
19+
(() → core::Null? {
20+
value = this.{self::A::baz}();
21+
intValue = 42;
22+
}).call();
23+
return result;
24+
}
25+
}
26+
static method main() → dynamic {}

0 commit comments

Comments
 (0)