mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:30:32 +00:00
[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:
parent
0f8e17083b
commit
237c6eef9e
|
@ -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(
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in a new issue