4cb5b99718
Change-Id: I526d54f6976b28b171bf3c414b93e36dc6da508e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165000 Reviewed-by: Bob Nystrom <rnystrom@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
1088 lines
16 KiB
Dart
1088 lines
16 KiB
Dart
// 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++;
|
|
// ^
|
|
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
|
|
// [cfe] Final variable 'x' might already be assigned at this point.
|
|
}
|
|
|
|
{
|
|
final dynamic x;
|
|
x = 3;
|
|
++x;
|
|
// ^
|
|
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
|
|
// [cfe] Final variable 'x' might already be assigned at this point.
|
|
}
|
|
|
|
{
|
|
final dynamic x;
|
|
x = 3;
|
|
-x;
|
|
}
|
|
|
|
{
|
|
final dynamic x;
|
|
x = 3;
|
|
x += 3;
|
|
// ^
|
|
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
|
|
// [cfe] Final variable 'x' might already be assigned at this point.
|
|
}
|
|
|
|
{
|
|
final dynamic x;
|
|
x = 3;
|
|
x ??= 3;
|
|
// ^
|
|
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
|
|
// [cfe] Final variable 'x' might already be assigned at this point.
|
|
}
|
|
|
|
{
|
|
final dynamic x;
|
|
x = 3;
|
|
x ?? 3;
|
|
}
|
|
|
|
{
|
|
final dynamic x;
|
|
x = 3;
|
|
3 ?? x;
|
|
// ^
|
|
// [cfe] Operand of null-aware operation '??' has type 'int' which excludes null.
|
|
// ^
|
|
// [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
testDefinitelyUnassignedReads<int>();
|
|
testPotentiallyUnassignedReads<int>(true, 0);
|
|
testDefinitelyAssignedReads<int>(0);
|
|
testDefinitelyUnassignedReadForms();
|
|
testPotentiallyUnassignedReadForms(true);
|
|
testDefinitelyAssignedReadForms();
|
|
}
|