[cfe] Improve support for new invocation nodes in constant evaluator

* FunctionInvocation and LocalFunctionInvocation nodes are now supported.
* Handling of List getters is added to InstanceGet.
* Removed incorrect constant evaluation of .hashCode and .runtimeType
  for List constants.

Issue: https://github.com/dart-lang/sdk/issues/45340
Change-Id: I73f3e64e805c0753325463b3e777a6c1b7d0b5fb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198181
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2021-05-09 20:04:38 +00:00 committed by commit-bot@chromium.org
parent 0f8e17083b
commit 237c6eef9e
10 changed files with 181 additions and 174 deletions

View file

@ -1230,8 +1230,11 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
} else {
bool sentinelInserted = false;
if (nodeCache.containsKey(node)) {
bool isRecursiveFunctionCall =
node is MethodInvocation || node is StaticInvocation;
bool isRecursiveFunctionCall = node is MethodInvocation ||
node is InstanceInvocation ||
node is FunctionInvocation ||
node is LocalFunctionInvocation ||
node is StaticInvocation;
if (nodeCache[node] == null &&
!(enableConstFunctions && isRecursiveFunctionCall)) {
// recursive call
@ -2021,12 +2024,70 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
@override
Constant visitFunctionInvocation(FunctionInvocation node) {
return createInvalidExpressionConstant(node, "function invocation");
if (!enableConstFunctions) {
return createInvalidExpressionConstant(node, "function invocation");
}
final Constant receiver = _evaluateSubexpression(node.receiver);
if (receiver is AbortConstant) return receiver;
return _evaluateFunctionInvocation(node, receiver, node.arguments);
}
@override
Constant visitLocalFunctionInvocation(LocalFunctionInvocation node) {
return createInvalidExpressionConstant(node, "local function invocation");
if (!enableConstFunctions) {
return createInvalidExpressionConstant(node, "local function invocation");
}
final Constant receiver = env.lookupVariable(node.variable);
assert(receiver != null);
if (receiver is AbortConstant) return receiver;
return _evaluateFunctionInvocation(node, receiver, node.arguments);
}
Constant _evaluateFunctionInvocation(
TreeNode node, Constant receiver, Arguments argumentsNode) {
final List<Constant> arguments =
_evaluatePositionalArguments(argumentsNode);
if (arguments == null && _gotError != null) {
AbortConstant error = _gotError;
_gotError = null;
return error;
}
assert(_gotError == null);
assert(arguments != null);
// Evaluate type arguments of the function invoked.
List<DartType> types = _evaluateTypeArguments(node, argumentsNode);
if (types == null && _gotError != null) {
AbortConstant error = _gotError;
_gotError = null;
return error;
}
assert(_gotError == null);
assert(types != null);
// Evaluate named arguments of the function invoked.
final Map<String, Constant> named = _evaluateNamedArguments(argumentsNode);
if (named == null && _gotError != null) {
AbortConstant error = _gotError;
_gotError = null;
return error;
}
assert(_gotError == null);
assert(named != null);
if (receiver is FunctionValue) {
return _handleFunctionInvocation(
receiver.function, types, arguments, named,
functionEnvironment: receiver.environment);
} else {
return createInvalidExpressionConstant(
node, "function invocation with invalid receiver");
}
}
@override
@ -2537,6 +2598,38 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
interfaceTarget: node.interfaceTarget));
} else if (receiver is NullConstant) {
return createErrorConstant(node, messageConstEvalNullValue);
} else if (receiver is ListConstant && enableConstFunctions) {
switch (node.name.text) {
case 'first':
if (receiver.entries.isEmpty) {
return new _AbortDueToThrowConstant(
node, new StateError('No element'));
}
return receiver.entries.first;
case 'isEmpty':
return new BoolConstant(receiver.entries.isEmpty);
case 'isNotEmpty':
return new BoolConstant(receiver.entries.isNotEmpty);
// TODO(kallentu): case 'iterator'
case 'last':
if (receiver.entries.isEmpty) {
return new _AbortDueToThrowConstant(
node, new StateError('No element'));
}
return receiver.entries.last;
case 'length':
return new IntConstant(receiver.entries.length);
// TODO(kallentu): case 'reversed'
case 'single':
if (receiver.entries.isEmpty) {
return new _AbortDueToThrowConstant(
node, new StateError('No element'));
} else if (receiver.entries.length > 1) {
return new _AbortDueToThrowConstant(
node, new StateError('Too many elements'));
}
return receiver.entries.single;
}
} else if (receiver is InstanceConstant && enableConstFunctions) {
for (final Reference fieldRef in receiver.fieldValues.keys) {
final Field field = fieldRef.asField;
@ -2629,8 +2722,6 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
node, new StateError('No element'));
}
return receiver.entries.first;
case 'hashCode':
return new IntConstant(receiver.entries.hashCode);
case 'isEmpty':
return new BoolConstant(receiver.entries.isEmpty);
case 'isNotEmpty':
@ -2645,8 +2736,6 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
case 'length':
return new IntConstant(receiver.entries.length);
// TODO(kallentu): case 'reversed'
case 'runtimeType':
return new TypeLiteralConstant(receiver.typeArgument);
case 'single':
if (receiver.entries.isEmpty) {
return new _AbortDueToThrowConstant(

View file

@ -86,13 +86,6 @@ int singleCatchFn2() {
return 1;
}
const typeExample = int;
const typeVar = typeFn();
Type typeFn() {
const List<int> x = [1, 2];
return x.runtimeType;
}
const getWithIndexVar = getWithIndexFn();
int getWithIndexFn() {
const List<int> x = [1];
@ -134,7 +127,6 @@ void main() {
Expect.equals(singleVar, 1);
Expect.equals(singleCatchVar, 0);
Expect.equals(singleCatchVar2, 0);
Expect.equals(typeVar, int);
Expect.equals(getWithIndexVar, 1);
Expect.equals(rangeErrorCatchVar, 0);
Expect.equals(mutableListVar, const [1, 2]);

View file

@ -15,18 +15,16 @@ static const field core::int lengthVar = #C5;
static const field core::int singleVar = #C1;
static const field core::int singleCatchVar = #C2;
static const field core::int singleCatchVar2 = #C2;
static const field core::Type typeExample = #C6;
static const field core::Type typeVar = #C6;
static const field core::int getWithIndexVar = #C1;
static const field core::int rangeErrorCatchVar = #C2;
static const field core::List<core::int> mutableListVar = #C7;
static const field core::List<core::int> mutableListAddVar = #C9;
static const field core::List<core::int> mutableListVar = #C6;
static const field core::List<core::int> mutableListAddVar = #C8;
static method firstFn() → core::int {
return (#C7).{core::Iterable::first};
return (#C6).{core::Iterable::first};
}
static method firstCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::first};
core::int v = (#C9).{core::Iterable::first};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -34,17 +32,17 @@ static method firstCatchFn() → core::int {
return 1;
}
static method isEmptyFn() → core::bool {
return (#C7).{core::Iterable::isEmpty};
return (#C6).{core::Iterable::isEmpty};
}
static method isNotEmptyFn() → core::bool {
return (#C7).{core::Iterable::isNotEmpty};
return (#C6).{core::Iterable::isNotEmpty};
}
static method lastFn() → core::int {
return (#C7).{core::Iterable::last};
return (#C6).{core::Iterable::last};
}
static method lastCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::last};
core::int v = (#C9).{core::Iterable::last};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -52,14 +50,14 @@ static method lastCatchFn() → core::int {
return 1;
}
static method lengthFn() → core::int {
return (#C7).{core::List::length};
return (#C6).{core::List::length};
}
static method singleFn() → core::int {
return (#C11).{core::Iterable::single};
return (#C10).{core::Iterable::single};
}
static method singleCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::single};
core::int v = (#C9).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -68,22 +66,19 @@ static method singleCatchFn() → core::int {
}
static method singleCatchFn2() → core::int {
try {
core::int v = (#C7).{core::Iterable::single};
core::int v = (#C6).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
}
return 1;
}
static method typeFn() → core::Type {
return (#C7).{core::Object::runtimeType};
}
static method getWithIndexFn() → core::int {
return (#C11).{core::List::[]}(0);
return (#C10).{core::List::[]}(0);
}
static method rangeErrorCatchFn() → core::int {
try {
core::int v = (#C11).{core::List::[]}(1);
core::int v = (#C10).{core::List::[]}(1);
}
on core::RangeError catch(no-exception-var) {
return 0;
@ -110,11 +105,10 @@ static method main() → void {
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C7, #C7);
exp::Expect::equals(#C9, #C9);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C8, #C8);
}
constants {
@ -123,10 +117,9 @@ constants {
#C3 = false
#C4 = true
#C5 = 2
#C6 = TypeLiteralConstant(core::int)
#C7 = <core::int>[#C1, #C5]
#C8 = 3
#C9 = <core::int>[#C1, #C5, #C8]
#C10 = <core::int>[]
#C11 = <core::int>[#C1]
#C6 = <core::int>[#C1, #C5]
#C7 = 3
#C8 = <core::int>[#C1, #C5, #C7]
#C9 = <core::int>[]
#C10 = <core::int>[#C1]
}

View file

@ -15,18 +15,16 @@ static const field core::int lengthVar = #C5;
static const field core::int singleVar = #C1;
static const field core::int singleCatchVar = #C2;
static const field core::int singleCatchVar2 = #C2;
static const field core::Type typeExample = #C6;
static const field core::Type typeVar = #C6;
static const field core::int getWithIndexVar = #C1;
static const field core::int rangeErrorCatchVar = #C2;
static const field core::List<core::int> mutableListVar = #C7;
static const field core::List<core::int> mutableListAddVar = #C9;
static const field core::List<core::int> mutableListVar = #C6;
static const field core::List<core::int> mutableListAddVar = #C8;
static method firstFn() → core::int {
return (#C7).{core::Iterable::first};
return (#C6).{core::Iterable::first};
}
static method firstCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::first};
core::int v = (#C9).{core::Iterable::first};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -34,17 +32,17 @@ static method firstCatchFn() → core::int {
return 1;
}
static method isEmptyFn() → core::bool {
return (#C7).{core::Iterable::isEmpty};
return (#C6).{core::Iterable::isEmpty};
}
static method isNotEmptyFn() → core::bool {
return (#C7).{core::Iterable::isNotEmpty};
return (#C6).{core::Iterable::isNotEmpty};
}
static method lastFn() → core::int {
return (#C7).{core::Iterable::last};
return (#C6).{core::Iterable::last};
}
static method lastCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::last};
core::int v = (#C9).{core::Iterable::last};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -52,14 +50,14 @@ static method lastCatchFn() → core::int {
return 1;
}
static method lengthFn() → core::int {
return (#C7).{core::List::length};
return (#C6).{core::List::length};
}
static method singleFn() → core::int {
return (#C11).{core::Iterable::single};
return (#C10).{core::Iterable::single};
}
static method singleCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::single};
core::int v = (#C9).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -68,22 +66,19 @@ static method singleCatchFn() → core::int {
}
static method singleCatchFn2() → core::int {
try {
core::int v = (#C7).{core::Iterable::single};
core::int v = (#C6).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
}
return 1;
}
static method typeFn() → core::Type {
return (#C7).{core::Object::runtimeType};
}
static method getWithIndexFn() → core::int {
return (#C11).{core::List::[]}(0);
return (#C10).{core::List::[]}(0);
}
static method rangeErrorCatchFn() → core::int {
try {
core::int v = (#C11).{core::List::[]}(1);
core::int v = (#C10).{core::List::[]}(1);
}
on core::RangeError catch(no-exception-var) {
return 0;
@ -110,11 +105,10 @@ static method main() → void {
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C7, #C7);
exp::Expect::equals(#C9, #C9);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C8, #C8);
}
constants {
@ -123,10 +117,9 @@ constants {
#C3 = false
#C4 = true
#C5 = 2
#C6 = TypeLiteralConstant(core::int)
#C7 = <core::int>[#C1, #C5]
#C8 = 3
#C9 = <core::int>[#C1, #C5, #C8]
#C10 = <core::int>[]
#C11 = <core::int>[#C1]
#C6 = <core::int>[#C1, #C5]
#C7 = 3
#C8 = <core::int>[#C1, #C5, #C7]
#C9 = <core::int>[]
#C10 = <core::int>[#C1]
}

View file

@ -20,9 +20,6 @@ const singleCatchVar = singleCatchFn();
int singleCatchFn() {}
const singleCatchVar2 = singleCatchFn2();
int singleCatchFn2() {}
const typeExample = int;
const typeVar = typeFn();
Type typeFn() {}
const getWithIndexVar = getWithIndexFn();
int getWithIndexFn() {}
const rangeErrorCatchVar = rangeErrorCatchFn();

View file

@ -2,7 +2,6 @@ import "package:expect/expect.dart";
List<int> mutableList() {}
List<int> mutableListAdd() {}
Type typeFn() {}
bool isEmptyFn() {}
bool isNotEmptyFn() {}
const firstCatchVar = firstCatchFn();
@ -19,8 +18,6 @@ const rangeErrorCatchVar = rangeErrorCatchFn();
const singleCatchVar = singleCatchFn();
const singleCatchVar2 = singleCatchFn2();
const singleVar = singleFn();
const typeExample = int;
const typeVar = typeFn();
int firstCatchFn() {}
int firstFn() {}
int getWithIndexFn() {}

View file

@ -15,18 +15,16 @@ static const field core::int lengthVar = #C5;
static const field core::int singleVar = #C1;
static const field core::int singleCatchVar = #C2;
static const field core::int singleCatchVar2 = #C2;
static const field core::Type typeExample = #C6;
static const field core::Type typeVar = #C6;
static const field core::int getWithIndexVar = #C1;
static const field core::int rangeErrorCatchVar = #C2;
static const field core::List<core::int> mutableListVar = #C7;
static const field core::List<core::int> mutableListAddVar = #C9;
static const field core::List<core::int> mutableListVar = #C6;
static const field core::List<core::int> mutableListAddVar = #C8;
static method firstFn() → core::int {
return (#C7).{core::Iterable::first};
return (#C6).{core::Iterable::first};
}
static method firstCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::first};
core::int v = (#C9).{core::Iterable::first};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -34,17 +32,17 @@ static method firstCatchFn() → core::int {
return 1;
}
static method isEmptyFn() → core::bool {
return (#C7).{core::Iterable::isEmpty};
return (#C6).{core::Iterable::isEmpty};
}
static method isNotEmptyFn() → core::bool {
return (#C7).{core::Iterable::isNotEmpty};
return (#C6).{core::Iterable::isNotEmpty};
}
static method lastFn() → core::int {
return (#C7).{core::Iterable::last};
return (#C6).{core::Iterable::last};
}
static method lastCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::last};
core::int v = (#C9).{core::Iterable::last};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -52,14 +50,14 @@ static method lastCatchFn() → core::int {
return 1;
}
static method lengthFn() → core::int {
return (#C7).{core::List::length};
return (#C6).{core::List::length};
}
static method singleFn() → core::int {
return (#C11).{core::Iterable::single};
return (#C10).{core::Iterable::single};
}
static method singleCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::single};
core::int v = (#C9).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -68,22 +66,19 @@ static method singleCatchFn() → core::int {
}
static method singleCatchFn2() → core::int {
try {
core::int v = (#C7).{core::Iterable::single};
core::int v = (#C6).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
}
return 1;
}
static method typeFn() → core::Type {
return (#C7).{core::Object::runtimeType};
}
static method getWithIndexFn() → core::int {
return (#C11).{core::List::[]}(0);
return (#C10).{core::List::[]}(0);
}
static method rangeErrorCatchFn() → core::int {
try {
core::int v = (#C11).{core::List::[]}(1);
core::int v = (#C10).{core::List::[]}(1);
}
on core::RangeError catch(no-exception-var) {
return 0;
@ -110,11 +105,10 @@ static method main() → void {
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C7, #C7);
exp::Expect::equals(#C9, #C9);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C8, #C8);
}
constants {
@ -123,10 +117,9 @@ constants {
#C3 = false
#C4 = true
#C5 = 2
#C6 = TypeLiteralConstant(core::int*)
#C7 = <core::int*>[#C1, #C5]
#C8 = 3
#C9 = <core::int*>[#C1, #C5, #C8]
#C10 = <core::int*>[]
#C11 = <core::int*>[#C1]
#C6 = <core::int*>[#C1, #C5]
#C7 = 3
#C8 = <core::int*>[#C1, #C5, #C7]
#C9 = <core::int*>[]
#C10 = <core::int*>[#C1]
}

View file

@ -14,8 +14,6 @@ static const field core::int lengthVar = self::lengthFn();
static const field core::int singleVar = self::singleFn();
static const field core::int singleCatchVar = self::singleCatchFn();
static const field core::int singleCatchVar2 = self::singleCatchFn2();
static const field core::Type typeExample = core::int;
static const field core::Type typeVar = self::typeFn();
static const field core::int getWithIndexVar = self::getWithIndexFn();
static const field core::int rangeErrorCatchVar = self::rangeErrorCatchFn();
static const field core::List<core::int> mutableListVar = self::mutableList();
@ -40,8 +38,6 @@ static method singleCatchFn() → core::int
;
static method singleCatchFn2() → core::int
;
static method typeFn() → core::Type
;
static method getWithIndexFn() → core::int
;
static method rangeErrorCatchFn() → core::int
@ -52,8 +48,3 @@ static method mutableListAdd() → core::List<core::int>
;
static method main() → void
;
Extra constant evaluation status:
Evaluated: TypeLiteral @ org-dartlang-testcase:///const_functions_list.dart:89:21 -> TypeLiteralConstant(int*)
Extra constant evaluation: evaluated: 16, effectively constant: 1

View file

@ -15,18 +15,16 @@ static const field core::int lengthVar = #C5;
static const field core::int singleVar = #C1;
static const field core::int singleCatchVar = #C2;
static const field core::int singleCatchVar2 = #C2;
static const field core::Type typeExample = #C6;
static const field core::Type typeVar = #C6;
static const field core::int getWithIndexVar = #C1;
static const field core::int rangeErrorCatchVar = #C2;
static const field core::List<core::int> mutableListVar = #C7;
static const field core::List<core::int> mutableListAddVar = #C9;
static const field core::List<core::int> mutableListVar = #C6;
static const field core::List<core::int> mutableListAddVar = #C8;
static method firstFn() → core::int {
return (#C7).{core::Iterable::first};
return (#C6).{core::Iterable::first};
}
static method firstCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::first};
core::int v = (#C9).{core::Iterable::first};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -34,17 +32,17 @@ static method firstCatchFn() → core::int {
return 1;
}
static method isEmptyFn() → core::bool {
return (#C7).{core::Iterable::isEmpty};
return (#C6).{core::Iterable::isEmpty};
}
static method isNotEmptyFn() → core::bool {
return (#C7).{core::Iterable::isNotEmpty};
return (#C6).{core::Iterable::isNotEmpty};
}
static method lastFn() → core::int {
return (#C7).{core::Iterable::last};
return (#C6).{core::Iterable::last};
}
static method lastCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::last};
core::int v = (#C9).{core::Iterable::last};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -52,14 +50,14 @@ static method lastCatchFn() → core::int {
return 1;
}
static method lengthFn() → core::int {
return (#C7).{core::List::length};
return (#C6).{core::List::length};
}
static method singleFn() → core::int {
return (#C11).{core::Iterable::single};
return (#C10).{core::Iterable::single};
}
static method singleCatchFn() → core::int {
try {
core::int v = (#C10).{core::Iterable::single};
core::int v = (#C9).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
@ -68,22 +66,19 @@ static method singleCatchFn() → core::int {
}
static method singleCatchFn2() → core::int {
try {
core::int v = (#C7).{core::Iterable::single};
core::int v = (#C6).{core::Iterable::single};
}
on core::StateError catch(no-exception-var) {
return 0;
}
return 1;
}
static method typeFn() → core::Type {
return (#C7).{core::Object::runtimeType};
}
static method getWithIndexFn() → core::int {
return (#C11).{core::List::[]}(0);
return (#C10).{core::List::[]}(0);
}
static method rangeErrorCatchFn() → core::int {
try {
core::int v = (#C11).{core::List::[]}(1);
core::int v = (#C10).{core::List::[]}(1);
}
on core::RangeError catch(no-exception-var) {
return 0;
@ -110,11 +105,10 @@ static method main() → void {
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C1, 1);
exp::Expect::equals(#C2, 0);
exp::Expect::equals(#C7, #C7);
exp::Expect::equals(#C9, #C9);
exp::Expect::equals(#C6, #C6);
exp::Expect::equals(#C8, #C8);
}
constants {
@ -123,10 +117,9 @@ constants {
#C3 = false
#C4 = true
#C5 = 2
#C6 = TypeLiteralConstant(core::int*)
#C7 = <core::int*>[#C1, #C5]
#C8 = 3
#C9 = <core::int*>[#C1, #C5, #C8]
#C10 = <core::int*>[]
#C11 = <core::int*>[#C1]
#C6 = <core::int*>[#C1, #C5]
#C7 = 3
#C8 = <core::int*>[#C1, #C5, #C7]
#C9 = <core::int*>[]
#C10 = <core::int*>[#C1]
}

View file

@ -11,7 +11,6 @@ import "package:expect/expect.dart";
const firstVar = firstFn();
// ^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int firstFn() {
const List<int> x = [1, 2];
return x.first;
@ -20,7 +19,6 @@ int firstFn() {
const firstCatchVar = firstCatchFn();
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int firstCatchFn() {
try {
const List<int> x = [];
@ -31,19 +29,9 @@ int firstCatchFn() {
return 1;
}
const hashCodeVar = hashCodeFn();
// ^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int hashCodeFn() {
const List<int> x = [1, 2];
return x.hashCode;
}
const isEmptyVar = isEmptyFn();
// ^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
bool isEmptyFn() {
const List<int> x = [1, 2];
return x.isEmpty;
@ -52,7 +40,6 @@ bool isEmptyFn() {
const isNotEmptyVar = isNotEmptyFn();
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
bool isNotEmptyFn() {
const List<int> x = [1, 2];
return x.isNotEmpty;
@ -61,7 +48,6 @@ bool isNotEmptyFn() {
const lastVar = lastFn();
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int lastFn() {
const List<int> x = [1, 2];
return x.last;
@ -70,7 +56,6 @@ int lastFn() {
const lastCatchVar = lastCatchFn();
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int lastCatchFn() {
try {
const List<int> x = [];
@ -84,7 +69,6 @@ int lastCatchFn() {
const lengthVar = lengthFn();
// ^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int lengthFn() {
const List<int> x = [1, 2];
return x.length;
@ -93,7 +77,6 @@ int lengthFn() {
const singleVar = singleFn();
// ^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int singleFn() {
const List<int> x = [1];
return x.single;
@ -102,7 +85,6 @@ int singleFn() {
const singleCatchVar = singleCatchFn();
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int singleCatchFn() {
try {
const List<int> x = [];
@ -116,7 +98,6 @@ int singleCatchFn() {
const singleCatchVar2 = singleCatchFn2();
// ^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
int singleCatchFn2() {
try {
const List<int> x = [1, 2];
@ -127,16 +108,6 @@ int singleCatchFn2() {
return 1;
}
const typeExample = int;
const typeVar = typeFn();
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [web] Constant evaluation error:
Type typeFn() {
const List<int> x = [1, 2];
return x.runtimeType;
}
const getWithIndexVar = getWithIndexFn();
// ^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
@ -178,7 +149,6 @@ List<int> mutableListAdd() {
void main() {
Expect.equals(firstVar, 1);
Expect.equals(firstCatchVar, 0);
Expect.type<int>(hashCodeVar);
Expect.equals(isEmptyVar, false);
Expect.equals(isNotEmptyVar, true);
Expect.equals(lastVar, 2);
@ -187,7 +157,6 @@ void main() {
Expect.equals(singleVar, 1);
Expect.equals(singleCatchVar, 0);
Expect.equals(singleCatchVar2, 0);
Expect.equals(typeVar, int);
Expect.equals(getWithIndexVar, 1);
Expect.equals(rangeErrorCatchVar, 0);
Expect.equals(mutableListVar, const [1, 2]);