mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[cfe] NullConstant variable declaration value.
Change-Id: I6d5adea4d70d8cd34f565a729034e2636935033e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/197120 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Reviewed-by: Jake Macdonald <jakemac@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
parent
228b22101d
commit
2ac2871476
19 changed files with 296 additions and 5 deletions
|
@ -3056,7 +3056,21 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
if (value is AbortConstant) return value;
|
||||
env.addVariableValue(parameter, value);
|
||||
}
|
||||
return executeBody(function.body);
|
||||
|
||||
final Constant result = executeBody(function.body);
|
||||
if (result is NullConstant &&
|
||||
function.returnType.nullability == Nullability.nonNullable) {
|
||||
// Ensure that the evaluated constant returned is not null if the
|
||||
// function has a non-nullable return type.
|
||||
return createErrorConstant(
|
||||
function,
|
||||
templateConstEvalInvalidType.withArguments(
|
||||
result,
|
||||
function.returnType,
|
||||
result.getType(_staticTypeContext),
|
||||
isNonNullableByDefault));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (functionEnvironment != null) {
|
||||
|
@ -3822,6 +3836,8 @@ class StatementConstantEvaluator extends StatementVisitor<ExecutionStatus> {
|
|||
if (node.initializer != null) {
|
||||
value = evaluate(node.initializer);
|
||||
if (value is AbortConstant) return new AbortStatus(value);
|
||||
} else {
|
||||
value = new NullConstant();
|
||||
}
|
||||
exprEvaluator.env.addVariableValue(node, value);
|
||||
return const ProceedStatus();
|
||||
|
|
|
@ -62,6 +62,12 @@ int function8() {
|
|||
return a;
|
||||
}
|
||||
|
||||
const var9 = function9();
|
||||
int? function9() {
|
||||
int? x;
|
||||
return x;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(var1, 4);
|
||||
Expect.equals(var1_1, 5);
|
||||
|
@ -72,4 +78,5 @@ void main() {
|
|||
Expect.equals(var6, 2);
|
||||
Expect.equals(var7, 2);
|
||||
Expect.equals(var8, 2);
|
||||
Expect.equals(var9, null);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ static const field core::int var5 = #C6;
|
|||
static const field core::int var6 = #C5;
|
||||
static const field core::int var7 = #C5;
|
||||
static const field core::int var8 = #C5;
|
||||
static const field core::int? var9 = #C7;
|
||||
static method function1(core::int a, core::int b) → core::int {
|
||||
core::int x = 1.{core::num::+}(a).{core::num::+}(b);
|
||||
return x;
|
||||
|
@ -52,6 +53,10 @@ static method function8() → core::int {
|
|||
a = 2;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method function9() → core::int? {
|
||||
core::int? x;
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 4);
|
||||
exp::Expect::equals(#C2, 5);
|
||||
|
@ -62,6 +67,7 @@ static method main() → void {
|
|||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C7, null);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -71,4 +77,5 @@ constants {
|
|||
#C4 = 6
|
||||
#C5 = 2
|
||||
#C6 = -2
|
||||
#C7 = null
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ static const field core::int var5 = #C6;
|
|||
static const field core::int var6 = #C5;
|
||||
static const field core::int var7 = #C5;
|
||||
static const field core::int var8 = #C5;
|
||||
static const field core::int? var9 = #C7;
|
||||
static method function1(core::int a, core::int b) → core::int {
|
||||
core::int x = 1.{core::num::+}(a).{core::num::+}(b);
|
||||
return x;
|
||||
|
@ -52,6 +53,10 @@ static method function8() → core::int {
|
|||
a = 2;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method function9() → core::int? {
|
||||
core::int? x;
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 4);
|
||||
exp::Expect::equals(#C2, 5);
|
||||
|
@ -62,6 +67,7 @@ static method main() → void {
|
|||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C7, null);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -71,8 +77,9 @@ constants {
|
|||
#C4 = 6
|
||||
#C5 = 2
|
||||
#C6 = -2
|
||||
#C7 = null
|
||||
}
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_variable_declarations.dart:71:23 -> IntConstant(-2)
|
||||
Extra constant evaluation: evaluated: 33, effectively constant: 1
|
||||
Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_variable_declarations.dart:77:23 -> IntConstant(-2)
|
||||
Extra constant evaluation: evaluated: 35, effectively constant: 1
|
||||
|
|
|
@ -17,4 +17,6 @@ const var7 = function7();
|
|||
int function7() {}
|
||||
const var8 = function8();
|
||||
int function8() {}
|
||||
const var9 = function9();
|
||||
int? function9() {}
|
||||
void main() {}
|
||||
|
|
|
@ -10,6 +10,8 @@ const var5 = function5();
|
|||
const var6 = function6();
|
||||
const var7 = function7();
|
||||
const var8 = function8();
|
||||
const var9 = function9();
|
||||
int? function9() {}
|
||||
int function1(int a, int b) {}
|
||||
int function3() {}
|
||||
int function4() {}
|
||||
|
|
|
@ -14,6 +14,7 @@ static const field core::int var5 = #C6;
|
|||
static const field core::int var6 = #C5;
|
||||
static const field core::int var7 = #C5;
|
||||
static const field core::int var8 = #C5;
|
||||
static const field core::int? var9 = #C7;
|
||||
static method function1(core::int a, core::int b) → core::int {
|
||||
core::int x = 1.{core::num::+}(a).{core::num::+}(b);
|
||||
return x;
|
||||
|
@ -52,6 +53,10 @@ static method function8() → core::int {
|
|||
a = 2;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method function9() → core::int? {
|
||||
core::int? x;
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 4);
|
||||
exp::Expect::equals(#C2, 5);
|
||||
|
@ -62,6 +67,7 @@ static method main() → void {
|
|||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C7, null);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -71,4 +77,5 @@ constants {
|
|||
#C4 = 6
|
||||
#C5 = 2
|
||||
#C6 = -2
|
||||
#C7 = null
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ static const field core::int var5 = self::function5();
|
|||
static const field core::int var6 = self::function6();
|
||||
static const field core::int var7 = self::function7();
|
||||
static const field core::int var8 = self::function8();
|
||||
static const field core::int? var9 = self::function9();
|
||||
static method function1(core::int a, core::int b) → core::int
|
||||
;
|
||||
static method function2() → core::String
|
||||
|
@ -29,5 +30,7 @@ static method function7() → core::int
|
|||
;
|
||||
static method function8() → core::int
|
||||
;
|
||||
static method function9() → core::int?
|
||||
;
|
||||
static method main() → void
|
||||
;
|
||||
|
|
|
@ -14,6 +14,7 @@ static const field core::int var5 = #C6;
|
|||
static const field core::int var6 = #C5;
|
||||
static const field core::int var7 = #C5;
|
||||
static const field core::int var8 = #C5;
|
||||
static const field core::int? var9 = #C7;
|
||||
static method function1(core::int a, core::int b) → core::int {
|
||||
core::int x = 1.{core::num::+}(a).{core::num::+}(b);
|
||||
return x;
|
||||
|
@ -52,6 +53,10 @@ static method function8() → core::int {
|
|||
a = 2;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method function9() → core::int? {
|
||||
core::int? x;
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 4);
|
||||
exp::Expect::equals(#C2, 5);
|
||||
|
@ -62,6 +67,7 @@ static method main() → void {
|
|||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C5, 2);
|
||||
exp::Expect::equals(#C7, null);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -71,8 +77,9 @@ constants {
|
|||
#C4 = 6
|
||||
#C5 = 2
|
||||
#C6 = -2
|
||||
#C7 = null
|
||||
}
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_variable_declarations.dart:71:23 -> IntConstant(-2)
|
||||
Extra constant evaluation: evaluated: 33, effectively constant: 1
|
||||
Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_variable_declarations.dart:77:23 -> IntConstant(-2)
|
||||
Extra constant evaluation: evaluated: 35, effectively constant: 1
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests erroneous variable declaration usage within const functions.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn1();
|
||||
int fn1() {
|
||||
var a;
|
||||
return a;
|
||||
}
|
||||
|
||||
const var2 = fn2();
|
||||
int fn2() {
|
||||
var x;
|
||||
x = "string";
|
||||
return x;
|
||||
}
|
||||
|
||||
void main() {}
|
|
@ -0,0 +1,41 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:14: Error: Constant evaluation error:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:12:10: Context: Expected constant 'null' to be of type 'int', but was of type 'Null'.
|
||||
// return a;
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:7: Context: While analyzing:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:14: Error: Constant evaluation error:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:19:10: Context: Expected constant '"string"' to be of type 'int', but was of type 'String'.
|
||||
// return x;
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:7: Context: While analyzing:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = invalid-expression "Expected constant 'null' to be of type 'int', but was of type 'Null'.";
|
||||
static const field core::int var2 = invalid-expression "Expected constant '\"string\"' to be of type 'int', but was of type 'String'.";
|
||||
static method fn1() → core::int {
|
||||
dynamic a;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method fn2() → core::int {
|
||||
dynamic x;
|
||||
x = "string";
|
||||
return x as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method main() → void {}
|
|
@ -0,0 +1,41 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:14: Error: Constant evaluation error:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:12:10: Context: Expected constant 'null' to be of type 'int', but was of type 'Null'.
|
||||
// return a;
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:7: Context: While analyzing:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:14: Error: Constant evaluation error:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:19:10: Context: Expected constant '"string"' to be of type 'int', but was of type 'String'.
|
||||
// return x;
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:7: Context: While analyzing:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = invalid-expression "Expected constant 'null' to be of type 'int', but was of type 'Null'.";
|
||||
static const field core::int var2 = invalid-expression "Expected constant '\"string\"' to be of type 'int', but was of type 'String'.";
|
||||
static method fn1() → core::int {
|
||||
dynamic a;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method fn2() → core::int {
|
||||
dynamic x;
|
||||
x = "string";
|
||||
return x as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method main() → void {}
|
|
@ -0,0 +1,7 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn1();
|
||||
int fn1() {}
|
||||
const var2 = fn2();
|
||||
int fn2() {}
|
||||
void main() {}
|
|
@ -0,0 +1,7 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn1();
|
||||
const var2 = fn2();
|
||||
int fn1() {}
|
||||
int fn2() {}
|
||||
void main() {}
|
|
@ -0,0 +1,41 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:14: Error: Constant evaluation error:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:10:8: Context: Expected constant 'null' to be of type 'int', but was of type 'Null'.
|
||||
// int fn1() {
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:7: Context: While analyzing:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:14: Error: Constant evaluation error:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:19:10: Context: Expected constant '"string"' to be of type 'int', but was of type 'String'.
|
||||
// return x;
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:7: Context: While analyzing:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = invalid-expression "Expected constant 'null' to be of type 'int', but was of type 'Null'.";
|
||||
static const field core::int var2 = invalid-expression "Expected constant '\"string\"' to be of type 'int', but was of type 'String'.";
|
||||
static method fn1() → core::int {
|
||||
dynamic a;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method fn2() → core::int {
|
||||
dynamic x;
|
||||
x = "string";
|
||||
return x as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method main() → void {}
|
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = self::fn1();
|
||||
static const field core::int var2 = self::fn2();
|
||||
static method fn1() → core::int
|
||||
;
|
||||
static method fn2() → core::int
|
||||
;
|
||||
static method main() → void
|
||||
;
|
|
@ -0,0 +1,41 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:14: Error: Constant evaluation error:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:10:8: Context: Expected constant 'null' to be of type 'int', but was of type 'Null'.
|
||||
// int fn1() {
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:9:7: Context: While analyzing:
|
||||
// const var1 = fn1();
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:14: Error: Constant evaluation error:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:19:10: Context: Expected constant '"string"' to be of type 'int', but was of type 'String'.
|
||||
// return x;
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_variable_declarations_error.dart:15:7: Context: While analyzing:
|
||||
// const var2 = fn2();
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = invalid-expression "Expected constant 'null' to be of type 'int', but was of type 'Null'.";
|
||||
static const field core::int var2 = invalid-expression "Expected constant '\"string\"' to be of type 'int', but was of type 'String'.";
|
||||
static method fn1() → core::int {
|
||||
dynamic a;
|
||||
return a as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method fn2() → core::int {
|
||||
dynamic x;
|
||||
x = "string";
|
||||
return x as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
|
||||
}
|
||||
static method main() → void {}
|
|
@ -16,3 +16,13 @@ int fn1() {
|
|||
var a;
|
||||
return a;
|
||||
}
|
||||
|
||||
const var2 = fn2();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
// [cfe] Constant evaluation error:
|
||||
int fn2() {
|
||||
var x;
|
||||
x = "string";
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,14 @@ int function8() {
|
|||
return a;
|
||||
}
|
||||
|
||||
const var9 = function9();
|
||||
// ^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int? function9() {
|
||||
int? x;
|
||||
return x;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(var1, 4);
|
||||
Expect.equals(var1_1, 5);
|
||||
|
@ -92,4 +100,5 @@ void main() {
|
|||
Expect.equals(var6, 2);
|
||||
Expect.equals(var7, 2);
|
||||
Expect.equals(var8, 2);
|
||||
Expect.equals(var9, null);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue