mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:51:29 +00:00
[cfe] Invalid empty return statements in const function invocations.
Change-Id: Id1408bff917200f3825846bd6d483e52ca326d5b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194840 Reviewed-by: Jake Macdonald <jakemac@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
parent
4b4ccbaa0d
commit
f9536375e1
|
@ -1036,15 +1036,22 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute the statement using the [StatementConstantEvaluator].
|
/// Execute a function body using the [StatementConstantEvaluator].
|
||||||
Constant execute(Statement statement) {
|
Constant executeBody(Statement statement) {
|
||||||
StatementConstantEvaluator statementEvaluator =
|
StatementConstantEvaluator statementEvaluator =
|
||||||
new StatementConstantEvaluator(this);
|
new StatementConstantEvaluator(this);
|
||||||
ExecutionStatus status = statement.accept(statementEvaluator);
|
ExecutionStatus status = statement.accept(statementEvaluator);
|
||||||
if (status is ReturnStatus) {
|
if (status is ReturnStatus) {
|
||||||
|
if (status.value == null) {
|
||||||
|
// Void return type from executing the function body.
|
||||||
|
return new NullConstant();
|
||||||
|
}
|
||||||
return status.value;
|
return status.value;
|
||||||
} else if (status is AbortStatus) {
|
} else if (status is AbortStatus) {
|
||||||
return status.error;
|
return status.error;
|
||||||
|
} else if (status is ProceedStatus) {
|
||||||
|
// No return statement in function body with void return type.
|
||||||
|
return new NullConstant();
|
||||||
}
|
}
|
||||||
return createInvalidExpressionConstant(statement,
|
return createInvalidExpressionConstant(statement,
|
||||||
'No valid constant returned from the execution of $statement.');
|
'No valid constant returned from the execution of $statement.');
|
||||||
|
@ -2870,7 +2877,7 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
||||||
if (value is AbortConstant) return value;
|
if (value is AbortConstant) return value;
|
||||||
env.addVariableValue(parameter, value);
|
env.addVariableValue(parameter, value);
|
||||||
}
|
}
|
||||||
return execute(function.body);
|
return executeBody(function.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (functionEnvironment != null) {
|
if (functionEnvironment != null) {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// 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 function invocation return types.
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
const var1 = fn();
|
||||||
|
void fn() {}
|
||||||
|
|
||||||
|
const var2 = fn2();
|
||||||
|
void fn2() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const var3 = fn3();
|
||||||
|
int? fn3() => null;
|
||||||
|
|
||||||
|
const var4 = fn4();
|
||||||
|
int? fn4() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Expect.equals((var1 as dynamic), null);
|
||||||
|
Expect.equals((var2 as dynamic), null);
|
||||||
|
Expect.equals(var3, null);
|
||||||
|
Expect.equals(var4, null);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
import "package:expect/expect.dart" as exp;
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
static const field void var1 = #C1;
|
||||||
|
static const field void var2 = #C1;
|
||||||
|
static const field core::int? var3 = #C1;
|
||||||
|
static const field core::int? var4 = #C1;
|
||||||
|
static method fn() → void {}
|
||||||
|
static method fn2() → void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static method fn3() → core::int?
|
||||||
|
return null;
|
||||||
|
static method fn4() → core::int? {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static method main() → void {
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
constants {
|
||||||
|
#C1 = null
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
import "package:expect/expect.dart" as exp;
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
static const field void var1 = #C1;
|
||||||
|
static const field void var2 = #C1;
|
||||||
|
static const field core::int? var3 = #C1;
|
||||||
|
static const field core::int? var4 = #C1;
|
||||||
|
static method fn() → void {}
|
||||||
|
static method fn2() → void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static method fn3() → core::int?
|
||||||
|
return null;
|
||||||
|
static method fn4() → core::int? {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static method main() → void {
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
constants {
|
||||||
|
#C1 = null
|
||||||
|
}
|
||||||
|
|
||||||
|
Extra constant evaluation status:
|
||||||
|
Evaluated: AsExpression @ org-dartlang-testcase:///const_functions_return.dart:26:23 -> NullConstant(null)
|
||||||
|
Evaluated: AsExpression @ org-dartlang-testcase:///const_functions_return.dart:27:23 -> NullConstant(null)
|
||||||
|
Extra constant evaluation: evaluated: 6, effectively constant: 2
|
|
@ -0,0 +1,11 @@
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
const var1 = fn();
|
||||||
|
void fn() {}
|
||||||
|
const var2 = fn2();
|
||||||
|
void fn2() {}
|
||||||
|
const var3 = fn3();
|
||||||
|
int? fn3() => null;
|
||||||
|
const var4 = fn4();
|
||||||
|
int? fn4() {}
|
||||||
|
void main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
const var1 = fn();
|
||||||
|
const var2 = fn2();
|
||||||
|
const var3 = fn3();
|
||||||
|
const var4 = fn4();
|
||||||
|
int? fn3() => null;
|
||||||
|
int? fn4() {}
|
||||||
|
void fn() {}
|
||||||
|
void fn2() {}
|
||||||
|
void main() {}
|
|
@ -0,0 +1,30 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
import "package:expect/expect.dart" as exp;
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
static const field void var1 = #C1;
|
||||||
|
static const field void var2 = #C1;
|
||||||
|
static const field core::int? var3 = #C1;
|
||||||
|
static const field core::int? var4 = #C1;
|
||||||
|
static method fn() → void {}
|
||||||
|
static method fn2() → void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static method fn3() → core::int?
|
||||||
|
return null;
|
||||||
|
static method fn4() → core::int? {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static method main() → void {
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
constants {
|
||||||
|
#C1 = null
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
static const field void var1 = self::fn();
|
||||||
|
static const field void var2 = self::fn2();
|
||||||
|
static const field core::int? var3 = self::fn3();
|
||||||
|
static const field core::int? var4 = self::fn4();
|
||||||
|
static method fn() → void
|
||||||
|
;
|
||||||
|
static method fn2() → void
|
||||||
|
;
|
||||||
|
static method fn3() → core::int?
|
||||||
|
;
|
||||||
|
static method fn4() → core::int?
|
||||||
|
;
|
||||||
|
static method main() → void
|
||||||
|
;
|
|
@ -0,0 +1,35 @@
|
||||||
|
library /*isNonNullableByDefault*/;
|
||||||
|
import self as self;
|
||||||
|
import "dart:core" as core;
|
||||||
|
import "package:expect/expect.dart" as exp;
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
static const field void var1 = #C1;
|
||||||
|
static const field void var2 = #C1;
|
||||||
|
static const field core::int? var3 = #C1;
|
||||||
|
static const field core::int? var4 = #C1;
|
||||||
|
static method fn() → void {}
|
||||||
|
static method fn2() → void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static method fn3() → core::int?
|
||||||
|
return null;
|
||||||
|
static method fn4() → core::int? {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
static method main() → void {
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals((#C1) as{ForNonNullableByDefault} dynamic, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
exp::Expect::equals(#C1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
constants {
|
||||||
|
#C1 = null
|
||||||
|
}
|
||||||
|
|
||||||
|
Extra constant evaluation status:
|
||||||
|
Evaluated: AsExpression @ org-dartlang-testcase:///const_functions_return.dart:26:23 -> NullConstant(null)
|
||||||
|
Evaluated: AsExpression @ org-dartlang-testcase:///const_functions_return.dart:27:23 -> NullConstant(null)
|
||||||
|
Extra constant evaluation: evaluated: 6, effectively constant: 2
|
|
@ -0,0 +1,40 @@
|
||||||
|
// 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 function invocation return types.
|
||||||
|
|
||||||
|
// SharedOptions=--enable-experiment=const-functions
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
const var1 = fn();
|
||||||
|
// ^^^^
|
||||||
|
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||||
|
void fn() {}
|
||||||
|
|
||||||
|
const var2 = fn2();
|
||||||
|
// ^^^^^
|
||||||
|
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||||
|
void fn2() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const var3 = fn3();
|
||||||
|
// ^^^^^
|
||||||
|
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||||
|
int? fn3() => null;
|
||||||
|
|
||||||
|
const var4 = fn4();
|
||||||
|
// ^^^^^
|
||||||
|
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||||
|
int? fn4() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Expect.equals((var1 as dynamic), null);
|
||||||
|
Expect.equals((var2 as dynamic), null);
|
||||||
|
Expect.equals(var3, null);
|
||||||
|
Expect.equals(var4, null);
|
||||||
|
}
|
Loading…
Reference in a new issue