Version 2.10.0-45.0.dev
Merge commit 'f3ce2d6c3342e317ae7d1bde5d5bed2d6ff7c31e' into 'dev'
diff --git a/DEPS b/DEPS
index f6b082a..1c1ebdf 100644
--- a/DEPS
+++ b/DEPS
@@ -118,7 +118,7 @@
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
"markdown_rev": "dbeafd47759e7dd0a167602153bb9c49fb5e5fe7",
"matcher_rev": "9cae8faa7868bf3a88a7ba45eb0bd128e66ac515",
- "mime_rev": "179b5e6a88f4b63f36dc1b8fcbc1e83e5e0cd3a7",
+ "mime_tag": "0.9.7",
"mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
"mustache_rev": "664737ecad027e6b96d0d1e627257efa0e46fcb1",
"oauth2_tag": "1.6.0",
@@ -363,7 +363,7 @@
Var("dart_root") + "/third_party/pkg/matcher":
Var("dart_git") + "matcher.git" + "@" + Var("matcher_rev"),
Var("dart_root") + "/third_party/pkg/mime":
- Var("dart_git") + "mime.git" + "@" + Var("mime_rev"),
+ Var("dart_git") + "mime.git" + "@" + Var("mime_tag"),
Var("dart_root") + "/third_party/pkg/mockito":
Var("dart_git") + "mockito.git" + "@" + Var("mockito_rev"),
Var("dart_root") + "/third_party/pkg/mustache":
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 1370243..d605b1c 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -528,6 +528,9 @@
/// or `@Deprecated('..')`.
bool get hasDeprecated;
+ /// Return `true` if this element has an annotation of the form `@doNotStore`.
+ bool get hasDoNotStore;
+
/// Return `true` if this element has an annotation of the form `@factory`.
bool get hasFactory;
@@ -702,6 +705,10 @@
/// deprecated.
bool get isDeprecated;
+ /// Return `true` if this annotation marks the associated element as not to be
+ /// stored.
+ bool get isDoNotStore;
+
/// Return `true` if this annotation marks the associated member as a factory.
bool get isFactory;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index de0249e..3ad2cf9 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2284,6 +2284,10 @@
/// deprecated.
static const String _DEPRECATED_VARIABLE_NAME = "deprecated";
+ /// The name of the top-level variable used to mark an element as not to be
+ /// stored.
+ static const String _DO_NOT_STORE_VARIABLE_NAME = "doNotStore";
+
/// The name of the top-level variable used to mark a method as being a
/// factory.
static const String _FACTORY_VARIABLE_NAME = "factory";
@@ -2412,6 +2416,12 @@
}
@override
+ bool get isDoNotStore =>
+ element is PropertyAccessorElement &&
+ element.name == _DO_NOT_STORE_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
bool get isFactory =>
element is PropertyAccessorElement &&
element.name == _FACTORY_VARIABLE_NAME &&
@@ -2675,6 +2685,18 @@
}
@override
+ bool get hasDoNotStore {
+ var metadata = this.metadata;
+ for (var i = 0; i < metadata.length; i++) {
+ var annotation = metadata[i];
+ if (annotation.isDoNotStore) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
bool get hasFactory {
var metadata = this.metadata;
for (var i = 0; i < metadata.length; i++) {
@@ -5958,6 +5980,9 @@
bool get hasDeprecated => false;
@override
+ bool get hasDoNotStore => false;
+
+ @override
bool get hasFactory => false;
@override
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 8af1a69..655578d 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -451,6 +451,9 @@
bool get hasDeprecated => _declaration.hasDeprecated;
@override
+ bool get hasDoNotStore => _declaration.hasDoNotStore;
+
+ @override
bool get hasFactory => _declaration.hasFactory;
@override
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 11d59aa..9d8d3b9 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1587,6 +1587,7 @@
'CONST_EVAL_TYPE_TYPE',
"In constant expressions, operands of this operator must be of type "
"'Type'.");
+
/**
* Parameters:
* 0: the name of the type of the initializer expression
@@ -2534,7 +2535,7 @@
static const CompileTimeErrorCode EXPORT_LEGACY_SYMBOL = CompileTimeErrorCode(
'EXPORT_LEGACY_SYMBOL',
"The symbol '{0}' is defined in a legacy library, and can't be "
- "re-exported from a non-nullable by default library.",
+ "re-exported from a library with null safety enabled.",
correction: "Try removing the export or migrating the legacy library.",
hasPublishedDocs: true);
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 28e0d25..adfb44f 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -1907,7 +1907,7 @@
### export_legacy_symbol
_The symbol '{0}' is defined in a legacy library, and can't be re-exported from
-a non-nullable by default library._
+a library with null safety enabled._
#### Description
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 2656ab6..d1347c4 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -85,8 +85,8 @@
front_end/test/fasta/text_serialization_test: Pass, ExtraSlow
front_end/test/fasta/types/dart2js_benchmark_test: Pass, Slow
front_end/test/fasta/types/large_app_benchmark_test: Pass, ExtraSlow
-front_end/test/incremental_compiler_leak_test.dart: Pass, Slow
-front_end/test/incremental_dart2js_test.dart: Pass, Slow
+front_end/test/incremental_compiler_leak_test: Pass, Slow
+front_end/test/incremental_dart2js_test: Pass, Slow
front_end/test/minimal_incremental_kernel_generator_test: Slow, Pass
front_end/test/whole_program_test: Slow, Pass
front_end/testcases/*: Skip # These are not tests but input for tests.
diff --git a/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart b/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart
new file mode 100644
index 0000000..e7934e5
--- /dev/null
+++ b/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart
@@ -0,0 +1,1023 @@
+// Copyright (c) 2020, 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.
+
+/// To avoid having tests for the cross product of declaration forms and control
+/// flow constructs, the tests in this directory are split into tests that check
+/// that each different kind of variable declaration is treated appropriately
+/// with respect to errors and warnings for a single control flow construct; and
+/// tests that check that a reasonable subset of the possible control flow
+/// patterns produce the expected definite (un)-assignment behavior.
+///
+/// This test checks the latter.
+
+void use(Object? x) {}
+
+enum AorB { a, b }
+
+AorB aOrB = AorB.a;
+
+/// For two variable forms, test that definite un-assignment is correctly
+/// tracked for a variety of control flow structures. Each entry in this test
+/// declares a variable `int x` and a variable `late int y`, arranges for `x`
+/// and `y` to be in the definitely unassigned state, and then reads from
+/// each of them. It is expected that reading both `x` and `y` in this state
+/// is an error.
+///
+/// Each entry is guarded by a condition to ensure that all entries are
+/// reachable.
+void testDefiniteUnassignment(bool b) {
+ // Test unassignment in straightline code
+ if (b) {
+ int x;
+ late int y;
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Unreachable code inherits the state from the paths leading into it
+ // as if it were reachable.
+ if (b) {
+ int x;
+ late int y;
+ return;
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // An empty conditional does not change unassignment state
+ if (b) {
+ int x;
+ late int y;
+ if (b) {}
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Assignments in a branch that returns do not change unassignment state.
+ if (b) {
+ int x;
+ late int y;
+ if (b) {
+ x = 3;
+ y = 3;
+ return;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Assignments in a different branch do not change unassignment state.
+ if (b) {
+ int x;
+ late int y;
+ if (b) {
+ x = 3;
+ y = 3;
+ } else {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+ }
+
+ // Null-aware assignments are correctly recognized as unassigned. This test
+ // changes the pattern by using a final nullable variable to make the
+ // assignment non-trivial.
+ if (b) {
+ final int? x;
+ late int? y;
+ x ??= 3;
+// ^
+// [analyzer] unspecified
+// [cfe] unspecified
+ y ??= 3;
+// ^
+// [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+// [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // A while loop which does no assignments does not change unassignment state.
+ if (b) {
+ int x;
+ late int y;
+ while (b) {}
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Uses inside a while loop which does no assignments are definitely
+ // unassigned.
+ if (b) {
+ int x;
+ late int y;
+ while (b) {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+ }
+
+ // Uses inside a do while loop which does no assignments are definitely
+ // unassigned.
+ if (b) {
+ int x;
+ late int y;
+ do {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ } while (b);
+ }
+
+ // Uses inside a switch which assigns in a different branch are still
+ // definitely unassigned.
+ if (b) {
+ int x;
+ late int y;
+ switch (aOrB) {
+ case AorB.a:
+ x = 3;
+ y = 3;
+ break;
+ default:
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+ }
+
+ // Assignments in a branch of a switch which returns do not affect definite
+ // uassignment after the switch.
+ if (b) {
+ int x;
+ late int y;
+ switch (aOrB) {
+ case AorB.a:
+ x = 3;
+ y = 3;
+ return;
+ case AorB.b:
+ break;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Assignments in a closure do not affect definite unassignment before the
+ // closure is introduced.
+ if (b) {
+ int x;
+ late int y;
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ var f = () {
+ x = 3;
+ y = 3;
+ };
+ }
+
+ // Uses in a closure with no other assignments to the variables are recognized
+ // as definitely unassigned.
+ if (b) {
+ int x;
+ late int y;
+ var f = () {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ };
+ }
+
+ // Assignments in a late initializer do not affect definite unassignment
+ // before the late initializer is introduced.
+ if (b) {
+ int x;
+ late int y;
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ late int z1 = x = 3;
+ late int z2 = y = 3;
+ }
+
+ // Uses in a for loop test which are not assigned before or in the loop are
+ // definitely unassigned.
+ if (b) {
+ int x;
+ late int y;
+ for (; x < 0;) {}
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ for (; y < 0;) {}
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Uses in a for loop element test which are not assigned before or in the
+ // loop are definitely unassigned.
+ if (b) {
+ int x;
+ late int y;
+ [for (; x < 0;) 0];
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ [for (; y < 0;) 0];
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Uses in a for loop increment which are not assigned before or in the loop
+ // are definitely unassigned.
+ if (b) {
+ int x;
+ late int y;
+ for (;; x) {}
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ for (;; y) {}
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+
+ // Uses in a for loop element increment which are not assigned before or in
+ // the loop are definitely unassigned.
+ if (b) {
+ int x;
+ late int y;
+ [for (;; x) 0];
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ [for (;; y) 0];
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
+ // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+ }
+}
+
+/// For two variable forms, test that potential un-assignment is correctly
+/// tracked for a variety of control flow structures. Each entry in this test
+/// declares a variable `int x` and a variable `late int y`, arranges for `x`
+/// and `y` to be in the potentially (but not definitely) unassigned state, and
+/// then reads from each of them. It is expected that reading `x` in this state
+/// is an error, but reading `y` in this state is not an error.
+///
+/// Each entry is guarded by a condition to ensure that all entries are
+/// reachable.
+void testPotentialUnassignment(bool b) {
+ // Assignments in an `if` with no else result in a potentially unassigned
+ // state.
+ if (b) {
+ int x;
+ late int y;
+ if (b) {
+ x = 3;
+ y = 3;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Unreachable code inherits the state from the paths leading into it
+ // as if it were reachable.
+ if (b) {
+ int x;
+ late int y;
+ if (b) {
+ x = 3;
+ y = 3;
+ }
+ return;
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Assignments in one branch of a conditional and not the other result in a
+ // potentially unassigned state.
+ if (b) {
+ int x;
+ late int y;
+ if (b) {
+ x = 3;
+ y = 3;
+ } else {}
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Assignments in one branch of a conditional expression leave a variable in a
+ // potentially assigned state.
+ if (b) {
+ int x;
+ late int y;
+ b ? x = 3 : 3;
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ b ? y = 3 : 3;
+ use(y);
+ }
+
+ // Assignments in one branch of a conditional element leave a variable in a
+ // potentially assigned state.
+ if (b) {
+ int x;
+ late int y;
+ [if (b) x = 3];
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ [if (b) y = 3];
+ use(y);
+ }
+
+ // Joining a branch in which a variable is potentially assigned to a branch in
+ // which a variable is definitely assigned leave the variable in a potentially
+ // assigned state.
+ if (b) {
+ int x;
+ late int y;
+ if (b) {
+ if (b) {
+ x = 3;
+ y = 3;
+ }
+ } else {
+ x = 3;
+ y = 3;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Null-aware assignments leave a variable in a potentially assigned state.
+ // For non-late variables, this is a non-issue since the variable must be
+ // definitely assigned in order to perform the assignment. For late
+ // variables, we test this using a late final nullable variable in a
+ // potentially nullable state in the null-aware assignment, and then checking
+ // that both a use and an assignment are not erroneous, implying that the
+ // null-aware assignment has left the variable neither definitely assigned
+ // (since in this case the assignment would be erroneous), nor definitely
+ // unassigned (since in this case the read would be erroneous).
+ if (b) {
+ late final int? x;
+ late final int? y;
+ if (b) {
+ y = 3;
+ x = 3;
+ } // x and y are now potentially assigned.
+ x ??= 3;
+ y ??= 3;
+ use(x);
+ y = 3;
+ }
+
+ // Uses in a while loop which contains later assignments are treated as
+ // potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ while (b) {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ x = 3;
+ y = 3;
+ }
+ }
+
+ // Uses after a loop which contains assignments are treated as potentially
+ // assigned.
+ if (b) {
+ int x;
+ late int y;
+ while (b) {
+ x = 3;
+ y = 3;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Uses in a loop with assignments guarded by a conditional are treated as
+ // potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ while (b) {
+ if (b) {
+ x = 3;
+ y = 3;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+ }
+
+ // Uses in a do/while loop which contains assignment are treated as
+ // potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ do {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ x = 3;
+ y = 3;
+ } while (b);
+ }
+
+ // Uses in a do/while loop with assignments guarded by a condition are treated
+ // as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ do {
+ if (b) {
+ x = 3;
+ y = 3;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ } while (b);
+ }
+
+ // Uses after a switch which assigns in some branches but not in the default
+ // case are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ switch (aOrB) {
+ case AorB.a:
+ x = 3;
+ y = 3;
+ break;
+ default:
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Uses after a switch which assigns in one branch but not in the other case
+ // are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ switch (aOrB) {
+ case AorB.a:
+ x = 3;
+ y = 3;
+ break;
+ case AorB.b:
+ break;
+ }
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Uses in a closure when there are subsequent assignments in the enclosing
+ // function body are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ var f = () {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ };
+ x = 3;
+ y = 3;
+ }
+
+ // Uses in a closure when there are subsequent assignments in the closure body
+ // are treated as potentially unassigned.
+ if (b) {
+ int x;
+ late int y;
+ var f = () {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ x = 3;
+ y = 3;
+ };
+ }
+
+ // Uses in a closure when there are subsequent assignments in a subsequent
+ // closure are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ var f = () {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ };
+ var g = () {
+ x = 3;
+ y = 3;
+ };
+ }
+
+ // Uses in a closure when there are assignments in a previous closure are
+ // treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ var g = () {
+ x = 3;
+ y = 3;
+ };
+ var f = () {
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ };
+ }
+
+ // Uses after a closure which contains assignments has been introduced are
+ // treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ var f = () {
+ x = 3;
+ y = 3;
+ };
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Uses in a late initializer when there are subsequent assignments in the
+ // enclosing function body are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ late int z0 = x;
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ late int z1 = y;
+ x = 3;
+ y = 3;
+ }
+
+ // Uses in a late initializer when there are subsequent assignments in the
+ // late initializer are treated as potentially assigned, since late
+ // initializers may be re-executed if a previous execution failed to complete
+ // due to throwing an exception, or due to re-entering the initializer during
+ // execution.
+ if (b) {
+ int x;
+ late int y;
+ late int z0 = x + (x = 3);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ late int z1 = y + (y = 3);
+ }
+
+ // Uses in a late initializer when there are subsequent assignments in a
+ // subsequent late initializer are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ late int z0 = x;
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ late int z1 = y;
+ late int z3 = (x = 3) + (y = 3);
+ }
+
+ // Uses in a late initializer when there are assignments in a previous late
+ // initializer are treated as potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+
+ late int z3 = (x = 3) + (y = 3);
+
+ late int z0 = x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ late int z1 = y;
+ }
+
+ // Uses after a late initializer which contains assignments are treated as
+ // potentially assigned.
+ if (b) {
+ int x;
+ late int y;
+ late int z0 = x = 3;
+ late int z1 = y = 3;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ use(y);
+ }
+
+ // Uses of a for in loop index variable after the loop are potentially
+ // unassigned.
+ if (b) {
+ int x;
+ late int y;
+ for (x in []) {}
+ for (y in []) {}
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Uses of a for in element index variable after the loop are potentially
+ // unassigned.
+ if (b) {
+ int x;
+ late int y;
+ [for (x in []) 0];
+ [for (y in []) 0];
+ use(x);
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ use(y);
+ }
+
+ // Uses in a for loop test which are assigned in the loop but not before it
+ // are potentially unassigned.
+ if (b) {
+ int x;
+ late int y;
+ for (; x < 0;) {
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ x = 0;
+ }
+ for (; y < 0;) {
+ y = 0;
+ }
+ }
+
+ // Uses in a for loop element test which are assigned in the loop but not
+ // before it in the loop are potentially unassigned
+ if (b) {
+ int x;
+ late int y;
+ [for (; x < 0;) x = 0];
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE
+ // [cfe] Non-nullable variable 'x' must be assigned before it can be used.
+ [for (; y < 0;) y = 0];
+ }
+}
+
+/// For a single variable form, test that definite assignment is correctly
+/// tracked for a variety of control flow structures. Each entry in this test
+/// declares a variable `int x`, arranges for `x` to be in the definitely
+/// assigned state, and then reads from `x`. It is expected that reading `x` in
+/// this state is not an error.
+///
+/// Each entry is guarded by a condition to ensure that all entries are
+/// reachable.
+void testDefiniteAssignment(bool b) {
+ // A variable used after a straightline assignment is definitely assigned.
+ if (b) {
+ int x;
+ x = 3;
+ use(x);
+ }
+
+ // Unreachable code inherits the state from the paths leading into it
+ // as if it were reachable.
+ if (b) {
+ int x;
+ x = 3;
+ return;
+ use(x);
+ }
+
+ // A variable assigned in both branches of a conditional statement is
+ // definitely assigned after the conditional.
+ if (b) {
+ int x;
+ if (b) {
+ x = 3;
+ } else {
+ x = 3;
+ }
+ use(x);
+ }
+
+ // A variable assigned in both branches of a conditional expression is
+ // definitely assigned after the conditional.
+ if (b) {
+ int x;
+ b ? x = 3 : x = 3;
+ use(x);
+ }
+
+ // A variable assigned in both branches of a conditional element is
+ // definitely assigned after the conditional.
+ if (b) {
+ int x;
+ [if (b) x = 3 else x = 3];
+ use(x);
+ }
+
+ // A variable assigned in the only completing branch of a conditional
+ // statement is definitely assigned after the conditional.
+ if (b) {
+ int x;
+ if (b) {
+ x = 3;
+ } else {
+ return;
+ }
+ use(x);
+ }
+
+ // A variable assigned in the only completing branch of a conditional
+ // expression is definitely assigned after the conditional.
+ if (b) {
+ int x;
+ b ? x = 3 : throw "Return";
+ use(x);
+ }
+
+ // A variable assigned in the only completing branch of a conditional element
+ // is definitely assigned after the conditional.
+ if (b) {
+ int x;
+ [if (b) x = 3 else throw "Return"];
+ use(x);
+ }
+
+ // A variable assigned and used in a while loop is definitely assigned after
+ // the assignment.
+ if (b) {
+ int x;
+ while (b) {
+ x = 3;
+ use(x);
+ }
+ }
+
+ // A variable assigned and used in a do while loop is definitely assigned
+ // after the assignment, and after the loop.
+ if (b) {
+ int x;
+ do {
+ x = 3;
+ use(x);
+ } while (b);
+ use(x);
+ }
+
+ // A variable assigned in both branches of an exhaustive switch is definitely
+ // assigned after the switch.
+ if (b) {
+ int x;
+ switch (aOrB) {
+ case AorB.a:
+ x = 3;
+ break;
+ case AorB.b:
+ x = 3;
+ break;
+ }
+ use(x);
+ }
+
+ // A variable used in a closure which is allocated after the variable has been
+ // assigned is definitely assigned.
+ if (b) {
+ int x;
+ x = 3;
+ var f = () {
+ use(x);
+ };
+ }
+
+ // A variable used in a closure after being assigned in the closure is
+ // definitely assigned.
+ if (b) {
+ int x;
+ var f = () {
+ x = 3;
+ use(x);
+ };
+ }
+
+ // A variable used in a late initializer which is declared after the variable
+ // has been assigned is definitely assigned.
+ if (b) {
+ int x;
+ x = 3;
+ late int z = x;
+ }
+
+ // A variable used in a late initializer after being assigned in the
+ // initializer is definitely assigned.
+ if (b) {
+ int x;
+ late int z = (x = 3) + x;
+ }
+
+ // Uses of a for in loop index variable inside the loop are definitely
+ // assigned.
+ if (b) {
+ int x;
+ for (x in []) {
+ use(x);
+ }
+ }
+
+ // Uses of a for in element index variable inside the loop are definitely
+ // assigned.
+ if (b) {
+ int x;
+ [for (x in []) use(x)];
+ }
+
+ // Uses of a for in loop index variable inside the loop are definitely
+ // assigned.
+ if (b) {
+ for (int x in []) {
+ use(x);
+ }
+ }
+
+ // Uses of a for in element index variable inside the loop are definitely
+ // assigned.
+ if (b) {
+ [for (int x in []) use(x)];
+ }
+
+ // A variable which is assigned in the entry to a for loop is definitely
+ // assigned in the loop test and increment sections, and after the loop.
+ if (b) {
+ int x;
+ for (x = 0; x < 0; x++) {}
+ use(x);
+ }
+
+ // A variable which is assigned in the entry to a for loop element is
+ // definitely assigned in the loop test and increment sections, and after the
+ // loop.
+ if (b) {
+ int x;
+ [for (x = 0; x < 0; x++) 0];
+ use(x);
+ }
+
+ // Uses in a for loop increment which are assigned in the loop are definitely
+ // assigned.
+ if (b) {
+ int x;
+ for (;; x) {
+ x = 0;
+ }
+ }
+
+ // Uses in a for loop element increment which are assigned in the loop are
+ // definitely assigned.
+ if (b) {
+ int x;
+ [for (;; x) x = 0];
+ }
+}
+
+void main() {
+ testDefiniteUnassignment(false);
+ testPotentialUnassignment(false);
+ testDefiniteAssignment(false);
+}
diff --git a/tests/language/nnbd/definite_assignment/read_error_test.dart b/tests/language/nnbd/definite_assignment/read_error_test.dart
new file mode 100644
index 0000000..8da8c77
--- /dev/null
+++ b/tests/language/nnbd/definite_assignment/read_error_test.dart
@@ -0,0 +1,1071 @@
+// Copyright (c) 2020, 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.
+
+/// To avoid having tests for the cross product of declaration forms and control
+/// flow constructs, the tests in this directory are split into tests that check
+/// that each different kind of variable declaration is treated appropriately
+/// with respect to errors and warnings for a single control flow construct; and
+/// tests that check that a reasonable subset of the possible control flow
+/// patterns produce the expected definite (un)-assignment behavior.
+///
+/// This test checks the the read component of the former. That is, it tests
+/// errors associated with reads of local variables based on definite
+/// assignment.
+
+void use(Object? x) {}
+
+/// Test that a read of a definitely unassigned variable gives the correct error
+/// for each kind of variable.
+void testDefinitelyUnassignedReads<T>() {
+ // It is a compile time error to read a local variable when the variable is
+ // **definitely unassigned** unless the variable is non-`final`, and
+ // non-`late`, and has nullable type.
+
+ // Ok: non-final and nullably typed.
+ {
+ var x;
+ use(x);
+ }
+
+ // Error: final.
+ {
+ final x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: not nullable.
+ {
+ int x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Ok: non-final and nullably typed.
+ {
+ int? x;
+ use(x);
+ }
+
+ // Error: final and not nullable.
+ {
+ final int x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final.
+ {
+ final int? x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final and not nullable.
+ {
+ final T x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late
+ {
+ late var x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late and not nullable
+ {
+ late int x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late
+ {
+ late int? x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late and not nullable
+ {
+ late T x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late and final
+ {
+ late final x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late and final and not nullable
+ {
+ late final int x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late and final
+ {
+ late final int? x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: late and final and not nullable
+ {
+ late final T x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+/// Test that a read of a potentially unassigned variable gives the correct
+/// error for each kind of variable.
+void testPotentiallyUnassignedReads<T>(bool b, T t) {
+ // It is a compile time error to read a local variable when the variable is
+ // **potentially unassigned** unless the variable is non-final and has
+ // nullable type, or is `late`.
+
+ // Ok: non-final and nullable.
+ {
+ var x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Error: final.
+ {
+ final x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: not nullable.
+ {
+ int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Ok: non-final and nullable.
+ {
+ int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Error: final and not nullable.
+ {
+ final int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final.
+ {
+ final int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final and not nullable.
+ {
+ final T x;
+ T y = t;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Ok: late.
+ {
+ late var x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late T x;
+ T y = t;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late final x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late final int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late final int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+
+ // Ok: late.
+ {
+ late final T x;
+ T y = t;
+ if (b) {
+ x = y;
+ }
+ use(x);
+ }
+}
+
+/// Test that reading a definitely assigned variable is not an error.
+void testDefinitelyAssignedReads<T>(T t) {
+ // It is never an error to read a definitely assigned variable.
+
+ {
+ var x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ final x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ int x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ int? x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ final int x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ final int? x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ final T x;
+ T y = t;
+ x = y;
+ use(x);
+ }
+
+ {
+ late var x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ late int x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ late int? x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ late T x;
+ T y = t;
+ x = y;
+ use(x);
+ }
+
+ {
+ late final x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ late final int x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ late final int? x;
+ int y = 3;
+ x = y;
+ use(x);
+ }
+
+ {
+ late final T x;
+ T y = t;
+ x = y;
+ use(x);
+ }
+}
+
+/// Test that a read of a definitely unassigned variable gives the correct error
+/// for a single choice of declaration form, across a range of read constructs.
+///
+/// These tests declare a `final` variable of type `dynamic` with no initializer
+/// and no assignments, and test that it is an error to use the variable
+/// in a variety of syntactic positions.
+void testDefinitelyUnassignedReadForms() {
+ {
+ final dynamic x;
+ x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x(use);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x.foo;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x.foo();
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x.foo = 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x?.foo;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x..foo;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x[0];
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ ([3])[x];
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (x as int);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (x is int);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (x == null);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (null == x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (3 == x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (x == 3);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ (x == 3);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x++;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ ++x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ -x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x += 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x ??= 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x ?? 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ 3 ?? x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+/// Test that a read of a potentially unassigned variable gives the correct
+/// error for a single choice of declaration form, across a range of read
+/// constructs.
+///
+/// These tests declare a `final` variable of type `dynamic` and assign to it in
+/// one branch of a conditional such that the variable is potentially but not
+/// definitely assigned. The test then checks that it is an error to use the
+/// variable in a variety of syntactic positions.
+void testPotentiallyUnassignedReadForms(bool b) {
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ use(x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x(use);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x.foo;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x.foo();
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x.foo = 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x?.foo;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x..foo;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x[0];
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ ([3])[x];
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (x as int);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (x is int);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (x == null);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (null == x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (3 == x);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (x == 3);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ (x == 3);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x++;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ ++x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ -x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x += 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x ??= 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x ?? 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ 3 ?? x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+/// Test that a read of a definitely assigned variable is not an error for a
+/// single choice of declaration form, across a range of read constructs.
+///
+/// This test declares a final variable and then initializes it via an
+/// assignment. The test then verifies that it is not an error to read the
+/// variable in a variety of syntactic positions.
+void testDefinitelyAssignedReadForms() {
+ {
+ final dynamic x;
+ x = 3;
+ x;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ use(x);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x(use);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x.foo;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x.foo();
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x.foo = 3;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x?.foo;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x..foo;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x[0];
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ ([3])[x];
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (x as int);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (x is int);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (x == null);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (null == x);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (3 == x);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (x == 3);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ (x == 3);
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x++;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ ++x;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ -x;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x += 3;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x ??= 3;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x ?? 3;
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ 3 ?? x;
+ }
+}
+
+void main() {
+ testDefinitelyUnassignedReads<int>();
+ testPotentiallyUnassignedReads<int>(true, 0);
+ testDefinitelyAssignedReads<int>(0);
+ testDefinitelyUnassignedReadForms();
+ testPotentiallyUnassignedReadForms(true);
+ testDefinitelyAssignedReadForms();
+}
diff --git a/tests/language/nnbd/definite_assignment/write_error_test.dart b/tests/language/nnbd/definite_assignment/write_error_test.dart
new file mode 100644
index 0000000..81d27b6
--- /dev/null
+++ b/tests/language/nnbd/definite_assignment/write_error_test.dart
@@ -0,0 +1,619 @@
+// Copyright (c) 2020, 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.
+
+/// To avoid having tests for the cross product of declaration forms and control
+/// flow constructs, the tests in this directory are split into tests that check
+/// that each different kind of variable declaration is treated appropriately
+/// with respect to errors and warnings for a single control flow construct; and
+/// tests that check that a reasonable subset of the possible control flow
+/// patterns produce the expected definite (un)-assignment behavior.
+///
+/// This test checks the the write component of the former. That is, it tests
+/// errors associated with writes of local variables based on definite
+/// assignment.
+
+void use(Object? x) {}
+
+/// Test that it is never an error to write to a definitely unassigned local
+/// variable.
+void testDefinitelyUnassignedWrites<T>() {
+ {
+ var x;
+ x = 3;
+ }
+
+ {
+ final x;
+ x = 3;
+ }
+
+ {
+ int x;
+ x = 3;
+ }
+
+ {
+ int? x;
+ x = 3;
+ }
+
+ {
+ final int x;
+ x = 3;
+ }
+
+ {
+ final int? x;
+ x = 3;
+ }
+
+ {
+ final T x;
+ x = t;
+ }
+
+ {
+ late var x;
+ x = 3;
+ }
+
+ {
+ late int x;
+ x = 3;
+ }
+
+ {
+ late int? x;
+ x = 3;
+ }
+
+ {
+ late T x;
+ x = t;
+ }
+
+ {
+ late final x;
+ x = 3;
+ }
+
+ {
+ late final int x;
+ x = 3;
+ }
+
+ {
+ late final int? x;
+ x = 3;
+ }
+
+ {
+ late final T x;
+ x = t;
+ }
+}
+
+/// Test that writing to a potentially unassigned variable gives the correct
+/// error for each kind of variable.
+void testPotentiallyUnassignedWrites<T>(bool b, T t) {
+ // It is a compile time error to assign a value to a `final`, non-`late` local
+ // variable which is **potentially assigned**. Thus, it is *not* a compile
+ // time error to assign to a **definitely unassigned** `final` local variable.
+
+ // Ok: not final.
+ {
+ var x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = 3;
+ }
+
+ // Error: final.
+ {
+ final x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Ok: not final.
+ {
+ int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: not final.
+ {
+ int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Error: final.
+ {
+ final int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final.
+ {
+ final int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final.
+ {
+ final T x;
+ T y = t;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Ok: late.
+ {
+ late var x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late T x;
+ T y = t;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late final x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late final int x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late final int? x;
+ int y = 3;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+
+ // Ok: late.
+ {
+ late final T x;
+ T y = t;
+ if (b) {
+ x = y;
+ }
+ x = y;
+ }
+}
+
+/// Test that writing to a definitely assigned variable gives the correct
+/// error for each kind of variable.
+void testDefinitelyAssignedWrites<T>(T t) {
+ // It is a compile time error to assign a value to a `final`, non-`late` local
+ // variable which is **potentially assigned**. Thus, it is *not* a compile
+ // time error to assign to a **definitely unassigned** `final` local variable.
+
+ // It is a compile time error to assign a value to a `final`, `late` local
+ // variable if it is **definitely assigned**. Thus, it is *not* a compile time
+ // error to assign to a **potentially unassigned** `final`, `late` local
+ // variable.
+
+ // Ok: not final, not late.
+ {
+ var x;
+ int y = 3;
+ x = y;
+ x = y;
+ }
+
+ // Error: final.
+ {
+ final x;
+ int y = 3;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+
+ }
+
+ // Ok: not final, not late.
+ {
+ int x;
+ int y = 3;
+ x = y;
+ x = y;
+ }
+
+ // Ok: not final, not late.
+ {
+ int? x;
+ int y = 3;
+ x = y;
+ x = y;
+ }
+
+ // Error: final.
+ {
+ final int x;
+ int y = 3;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final.
+ {
+ final int? x;
+ int y = 3;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final.
+ {
+ final T x;
+ T y = t;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Ok: not final.
+ {
+ late var x;
+ int y = 3;
+ x = y;
+ x = y;
+ }
+
+ // Ok: not final.
+ {
+ late int x;
+ int y = 3;
+ x = y;
+ x = y;
+ }
+
+ // Ok: not final.
+ {
+ late int? x;
+ int y = 3;
+ x = y;
+ x = y;
+ }
+
+ // Ok: not final.
+ {
+ late T x;
+ T y = t;
+ x = y;
+ x = y;
+ }
+
+ // Error: final and late.
+ {
+ late final x;
+ int y = 3;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final and late.
+ {
+ late final int x;
+ int y = 3;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+
+ }
+
+ // Error: final and late.
+ {
+ late final int? x;
+ int y = 3;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ // Error: final and late.
+ {
+ late final T x;
+ T y = t;
+ x = y;
+ x = y;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+/// Test that a write to a definitely unassigned variable gives no error for a
+/// single choice of declaration form, across a range of write constructs. Note
+/// that some constructs in this test also involve reads, and hence may generate
+/// read errors. The expectations should reflect this.
+void testDefinitelyUnassignedWriteForms() {
+ {
+ final dynamic x;
+ x = 3;
+ }
+
+ {
+ final dynamic x;
+ use(x = 3);
+ }
+
+ {
+ final dynamic x;
+ // Should be a read error only
+ x++;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ // Should be a read error only
+ ++x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ // Should be a read error only
+ x += 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ // Should be a read error only
+ x ??= 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+/// Test that a write to a potentially unassigned variable gives the correct
+/// error for a single choice of declaration form, across a range of write
+/// constructs.
+void testPotentiallyUnassignedWriteForms(bool b) {
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ x = 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ use(x = 3);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ // Expect both a read and write error
+ x++;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ // Expect both a read and write error
+ ++x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ // Expect both a read and write error
+ x += 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ if (b) {
+ x = 3;
+ }
+ // Expect both a read and write error
+ x ??= 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+/// Test that a write to a definitely assigned variable gives the correct
+/// error for a single choice of declaration form, across a range of write
+/// constructs.
+void testDefinitelyAssignedWriteForms() {
+ {
+ final dynamic x;
+ x = 3;
+ x = 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ use(x = 3);
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x++;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ ++x;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x += 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+
+ {
+ final dynamic x;
+ x = 3;
+ x ??= 3;
+ // ^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ }
+}
+
+void main() {
+ testDefinitelyUnassignedWrites<int>(0);
+ testPotentiallyUnassignedWrites<int>(true, 0);
+ testDefinitelyAssignedWrites<int>(0);
+ testDefinitelyUnassignedWriteForms();
+ testPotentiallyUnassignedWriteForms(true);
+ testDefinitelyAssignedWriteForms();
+}
diff --git a/tools/VERSION b/tools/VERSION
index bec7b97..76682b3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 44
+PRERELEASE 45
PRERELEASE_PATCH 0
\ No newline at end of file