[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:
Kallen Tu 2021-04-29 15:36:15 +00:00 committed by commit-bot@chromium.org
parent 228b22101d
commit 2ac2871476
19 changed files with 296 additions and 5 deletions

View file

@ -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();

View file

@ -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);
}

View file

@ -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
}

View file

@ -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

View file

@ -17,4 +17,6 @@ const var7 = function7();
int function7() {}
const var8 = function8();
int function8() {}
const var9 = function9();
int? function9() {}
void main() {}

View file

@ -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() {}

View file

@ -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
}

View file

@ -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
;

View file

@ -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

View file

@ -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() {}

View file

@ -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 {}

View file

@ -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 {}

View file

@ -0,0 +1,7 @@
import "package:expect/expect.dart";
const var1 = fn1();
int fn1() {}
const var2 = fn2();
int fn2() {}
void main() {}

View file

@ -0,0 +1,7 @@
import "package:expect/expect.dart";
const var1 = fn1();
const var2 = fn2();
int fn1() {}
int fn2() {}
void main() {}

View file

@ -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 {}

View file

@ -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
;

View file

@ -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 {}

View file

@ -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;
}

View file

@ -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);
}