mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[cfe] Mutable lists and list add method in const functions.
Within constant evaluation, mutable lists can be created and altered with `add`. Change-Id: I4ad86e3bea768844835dd732bff3ae135d6df8fb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/197280 Commit-Queue: Kallen Tu <kallentu@google.com> Reviewed-by: Jake Macdonald <jakemac@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
e6a0238898
commit
68d133d949
20 changed files with 246 additions and 39 deletions
|
@ -88,8 +88,15 @@ abstract class _ListOrSetConstantBuilder<L extends Expression> {
|
|||
}
|
||||
|
||||
class ListConstantBuilder extends _ListOrSetConstantBuilder<ListLiteral> {
|
||||
/// If [true], builds a [MutableListConstant].
|
||||
///
|
||||
/// [MutableListConstant]s can be modified during constant evaluation, but
|
||||
/// still results in a normal constant list at runtime.
|
||||
final bool isMutable;
|
||||
|
||||
ListConstantBuilder(
|
||||
Expression original, DartType elementType, ConstantEvaluator evaluator)
|
||||
Expression original, DartType elementType, ConstantEvaluator evaluator,
|
||||
{this.isMutable: false})
|
||||
: super(original, elementType, evaluator);
|
||||
|
||||
@override
|
||||
|
@ -115,9 +122,13 @@ class ListConstantBuilder extends _ListOrSetConstantBuilder<ListLiteral> {
|
|||
Constant build() {
|
||||
if (parts.length == 1) {
|
||||
// Fully evaluated
|
||||
if (isMutable) {
|
||||
return new MutableListConstant(elementType, parts.single);
|
||||
}
|
||||
return evaluator
|
||||
.lowerListConstant(new ListConstant(elementType, parts.single));
|
||||
}
|
||||
// TODO(kallentu): Handle partially evaluated [isMutable] lists.
|
||||
List<Expression> lists = <Expression>[];
|
||||
for (Object part in parts) {
|
||||
if (part is List<Constant>) {
|
||||
|
|
|
@ -1337,11 +1337,12 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
|
||||
@override
|
||||
Constant visitListLiteral(ListLiteral node) {
|
||||
if (!node.isConst) {
|
||||
if (!node.isConst && !enableConstFunctions) {
|
||||
return createInvalidExpressionConstant(node, "Non-constant list literal");
|
||||
}
|
||||
final ListConstantBuilder builder =
|
||||
new ListConstantBuilder(node, convertType(node.typeArgument), this);
|
||||
final ListConstantBuilder builder = new ListConstantBuilder(
|
||||
node, convertType(node.typeArgument), this,
|
||||
isMutable: !node.isConst);
|
||||
// These expressions are at the same level, so one of them being
|
||||
// unevaluated doesn't mean a sibling is or has an unevaluated child.
|
||||
// We therefore reset it before each call, combine it and set it correctly
|
||||
|
@ -2259,6 +2260,12 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
typeEnvironment.coreTypes.intNonNullableRawType,
|
||||
other.getType(_staticTypeContext),
|
||||
isNonNullableByDefault));
|
||||
case 'add':
|
||||
if (receiver is MutableListConstant) {
|
||||
receiver.entries.add(other);
|
||||
return receiver;
|
||||
}
|
||||
return new _AbortDueToThrowConstant(node, new UnsupportedError(op));
|
||||
}
|
||||
}
|
||||
} else if (receiver is MapConstant && enableConstFunctions) {
|
||||
|
@ -4041,6 +4048,15 @@ class BreakStatus extends ExecutionStatus {
|
|||
BreakStatus(this.target);
|
||||
}
|
||||
|
||||
/// Mutable lists used within the [ConstantEvaluator].
|
||||
class MutableListConstant extends ListConstant {
|
||||
MutableListConstant(DartType typeArgument, List<Constant> entries)
|
||||
: super(typeArgument, entries);
|
||||
|
||||
@override
|
||||
String toString() => 'MutableListConstant(${toStringInternal()})';
|
||||
}
|
||||
|
||||
/// An intermediate result that is used for invoking function nodes with their
|
||||
/// respective environment within the [ConstantEvaluator].
|
||||
class FunctionValue implements Constant {
|
||||
|
|
|
@ -110,6 +110,19 @@ int rangeErrorCatchFn() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
const mutableListVar = mutableList();
|
||||
List<int> mutableList() {
|
||||
List<int> x = [1, 2];
|
||||
return x;
|
||||
}
|
||||
|
||||
const mutableListAddVar = mutableListAdd();
|
||||
List<int> mutableListAdd() {
|
||||
List<int> x = [1, 2];
|
||||
x.add(3);
|
||||
return x;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(firstVar, 1);
|
||||
Expect.equals(firstCatchVar, 0);
|
||||
|
@ -124,4 +137,6 @@ void main() {
|
|||
Expect.equals(typeVar, int);
|
||||
Expect.equals(getWithIndexVar, 1);
|
||||
Expect.equals(rangeErrorCatchVar, 0);
|
||||
Expect.equals(mutableListVar, const [1, 2]);
|
||||
Expect.equals(mutableListAddVar, const [1, 2, 3]);
|
||||
}
|
||||
|
|
|
@ -19,12 +19,14 @@ 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 method firstFn() → core::int {
|
||||
return (#C7).{core::Iterable::first};
|
||||
}
|
||||
static method firstCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::first};
|
||||
core::int v = (#C10).{core::Iterable::first};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -42,7 +44,7 @@ static method lastFn() → core::int {
|
|||
}
|
||||
static method lastCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::last};
|
||||
core::int v = (#C10).{core::Iterable::last};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -53,11 +55,11 @@ static method lengthFn() → core::int {
|
|||
return (#C7).{core::List::length};
|
||||
}
|
||||
static method singleFn() → core::int {
|
||||
return (#C9).{core::Iterable::single};
|
||||
return (#C11).{core::Iterable::single};
|
||||
}
|
||||
static method singleCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::single};
|
||||
core::int v = (#C10).{core::Iterable::single};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -77,17 +79,26 @@ static method typeFn() → core::Type {
|
|||
return (#C7).{core::Object::runtimeType};
|
||||
}
|
||||
static method getWithIndexFn() → core::int {
|
||||
return (#C9).{core::List::[]}(0);
|
||||
return (#C11).{core::List::[]}(0);
|
||||
}
|
||||
static method rangeErrorCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C9).{core::List::[]}(1);
|
||||
core::int v = (#C11).{core::List::[]}(1);
|
||||
}
|
||||
on core::RangeError catch(no-exception-var) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static method mutableList() → core::List<core::int> {
|
||||
core::List<core::int> x = <core::int>[1, 2];
|
||||
return x;
|
||||
}
|
||||
static method mutableListAdd() → core::List<core::int> {
|
||||
core::List<core::int> x = <core::int>[1, 2];
|
||||
x.{core::List::add}(3);
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 1);
|
||||
exp::Expect::equals(#C2, 0);
|
||||
|
@ -102,6 +113,8 @@ static method main() → void {
|
|||
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);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -112,6 +125,8 @@ constants {
|
|||
#C5 = 2
|
||||
#C6 = TypeLiteralConstant(core::int)
|
||||
#C7 = <core::int>[#C1, #C5]
|
||||
#C8 = <core::int>[]
|
||||
#C9 = <core::int>[#C1]
|
||||
#C8 = 3
|
||||
#C9 = <core::int>[#C1, #C5, #C8]
|
||||
#C10 = <core::int>[]
|
||||
#C11 = <core::int>[#C1]
|
||||
}
|
||||
|
|
|
@ -19,12 +19,14 @@ 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 method firstFn() → core::int {
|
||||
return (#C7).{core::Iterable::first};
|
||||
}
|
||||
static method firstCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::first};
|
||||
core::int v = (#C10).{core::Iterable::first};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -42,7 +44,7 @@ static method lastFn() → core::int {
|
|||
}
|
||||
static method lastCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::last};
|
||||
core::int v = (#C10).{core::Iterable::last};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -53,11 +55,11 @@ static method lengthFn() → core::int {
|
|||
return (#C7).{core::List::length};
|
||||
}
|
||||
static method singleFn() → core::int {
|
||||
return (#C9).{core::Iterable::single};
|
||||
return (#C11).{core::Iterable::single};
|
||||
}
|
||||
static method singleCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::single};
|
||||
core::int v = (#C10).{core::Iterable::single};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -77,17 +79,26 @@ static method typeFn() → core::Type {
|
|||
return (#C7).{core::Object::runtimeType};
|
||||
}
|
||||
static method getWithIndexFn() → core::int {
|
||||
return (#C9).{core::List::[]}(0);
|
||||
return (#C11).{core::List::[]}(0);
|
||||
}
|
||||
static method rangeErrorCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C9).{core::List::[]}(1);
|
||||
core::int v = (#C11).{core::List::[]}(1);
|
||||
}
|
||||
on core::RangeError catch(no-exception-var) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static method mutableList() → core::List<core::int> {
|
||||
core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
|
||||
return x;
|
||||
}
|
||||
static method mutableListAdd() → core::List<core::int> {
|
||||
core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
|
||||
x.{core::List::add}(3);
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 1);
|
||||
exp::Expect::equals(#C2, 0);
|
||||
|
@ -102,6 +113,8 @@ static method main() → void {
|
|||
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);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -112,6 +125,8 @@ constants {
|
|||
#C5 = 2
|
||||
#C6 = TypeLiteralConstant(core::int)
|
||||
#C7 = <core::int>[#C1, #C5]
|
||||
#C8 = <core::int>[]
|
||||
#C9 = <core::int>[#C1]
|
||||
#C8 = 3
|
||||
#C9 = <core::int>[#C1, #C5, #C8]
|
||||
#C10 = <core::int>[]
|
||||
#C11 = <core::int>[#C1]
|
||||
}
|
||||
|
|
|
@ -27,4 +27,8 @@ const getWithIndexVar = getWithIndexFn();
|
|||
int getWithIndexFn() {}
|
||||
const rangeErrorCatchVar = rangeErrorCatchFn();
|
||||
int rangeErrorCatchFn() {}
|
||||
const mutableListVar = mutableList();
|
||||
List<int> mutableList() {}
|
||||
const mutableListAddVar = mutableListAdd();
|
||||
List<int> mutableListAdd() {}
|
||||
void main() {}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
List<int> mutableList() {}
|
||||
List<int> mutableListAdd() {}
|
||||
Type typeFn() {}
|
||||
bool isEmptyFn() {}
|
||||
bool isNotEmptyFn() {}
|
||||
|
@ -11,6 +13,8 @@ const isNotEmptyVar = isNotEmptyFn();
|
|||
const lastCatchVar = lastCatchFn();
|
||||
const lastVar = lastFn();
|
||||
const lengthVar = lengthFn();
|
||||
const mutableListAddVar = mutableListAdd();
|
||||
const mutableListVar = mutableList();
|
||||
const rangeErrorCatchVar = rangeErrorCatchFn();
|
||||
const singleCatchVar = singleCatchFn();
|
||||
const singleCatchVar2 = singleCatchFn2();
|
||||
|
|
|
@ -19,12 +19,14 @@ 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 method firstFn() → core::int {
|
||||
return (#C7).{core::Iterable::first};
|
||||
}
|
||||
static method firstCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::first};
|
||||
core::int v = (#C10).{core::Iterable::first};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -42,7 +44,7 @@ static method lastFn() → core::int {
|
|||
}
|
||||
static method lastCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::last};
|
||||
core::int v = (#C10).{core::Iterable::last};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -53,11 +55,11 @@ static method lengthFn() → core::int {
|
|||
return (#C7).{core::List::length};
|
||||
}
|
||||
static method singleFn() → core::int {
|
||||
return (#C9).{core::Iterable::single};
|
||||
return (#C11).{core::Iterable::single};
|
||||
}
|
||||
static method singleCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::single};
|
||||
core::int v = (#C10).{core::Iterable::single};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -77,17 +79,26 @@ static method typeFn() → core::Type {
|
|||
return (#C7).{core::Object::runtimeType};
|
||||
}
|
||||
static method getWithIndexFn() → core::int {
|
||||
return (#C9).{core::List::[]}(0);
|
||||
return (#C11).{core::List::[]}(0);
|
||||
}
|
||||
static method rangeErrorCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C9).{core::List::[]}(1);
|
||||
core::int v = (#C11).{core::List::[]}(1);
|
||||
}
|
||||
on core::RangeError catch(no-exception-var) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static method mutableList() → core::List<core::int> {
|
||||
core::List<core::int> x = <core::int>[1, 2];
|
||||
return x;
|
||||
}
|
||||
static method mutableListAdd() → core::List<core::int> {
|
||||
core::List<core::int> x = <core::int>[1, 2];
|
||||
x.{core::List::add}(3);
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 1);
|
||||
exp::Expect::equals(#C2, 0);
|
||||
|
@ -102,6 +113,8 @@ static method main() → void {
|
|||
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);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -112,6 +125,8 @@ constants {
|
|||
#C5 = 2
|
||||
#C6 = TypeLiteralConstant(core::int*)
|
||||
#C7 = <core::int*>[#C1, #C5]
|
||||
#C8 = <core::int*>[]
|
||||
#C9 = <core::int*>[#C1]
|
||||
#C8 = 3
|
||||
#C9 = <core::int*>[#C1, #C5, #C8]
|
||||
#C10 = <core::int*>[]
|
||||
#C11 = <core::int*>[#C1]
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ 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();
|
||||
static const field core::List<core::int> mutableListAddVar = self::mutableListAdd();
|
||||
static method firstFn() → core::int
|
||||
;
|
||||
static method firstCatchFn() → core::int
|
||||
|
@ -44,10 +46,14 @@ static method getWithIndexFn() → core::int
|
|||
;
|
||||
static method rangeErrorCatchFn() → core::int
|
||||
;
|
||||
static method mutableList() → core::List<core::int>
|
||||
;
|
||||
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: 14, effectively constant: 1
|
||||
Extra constant evaluation: evaluated: 16, effectively constant: 1
|
||||
|
|
|
@ -19,12 +19,14 @@ 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 method firstFn() → core::int {
|
||||
return (#C7).{core::Iterable::first};
|
||||
}
|
||||
static method firstCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::first};
|
||||
core::int v = (#C10).{core::Iterable::first};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -42,7 +44,7 @@ static method lastFn() → core::int {
|
|||
}
|
||||
static method lastCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::last};
|
||||
core::int v = (#C10).{core::Iterable::last};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -53,11 +55,11 @@ static method lengthFn() → core::int {
|
|||
return (#C7).{core::List::length};
|
||||
}
|
||||
static method singleFn() → core::int {
|
||||
return (#C9).{core::Iterable::single};
|
||||
return (#C11).{core::Iterable::single};
|
||||
}
|
||||
static method singleCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C8).{core::Iterable::single};
|
||||
core::int v = (#C10).{core::Iterable::single};
|
||||
}
|
||||
on core::StateError catch(no-exception-var) {
|
||||
return 0;
|
||||
|
@ -77,17 +79,26 @@ static method typeFn() → core::Type {
|
|||
return (#C7).{core::Object::runtimeType};
|
||||
}
|
||||
static method getWithIndexFn() → core::int {
|
||||
return (#C9).{core::List::[]}(0);
|
||||
return (#C11).{core::List::[]}(0);
|
||||
}
|
||||
static method rangeErrorCatchFn() → core::int {
|
||||
try {
|
||||
core::int v = (#C9).{core::List::[]}(1);
|
||||
core::int v = (#C11).{core::List::[]}(1);
|
||||
}
|
||||
on core::RangeError catch(no-exception-var) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static method mutableList() → core::List<core::int> {
|
||||
core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
|
||||
return x;
|
||||
}
|
||||
static method mutableListAdd() → core::List<core::int> {
|
||||
core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
|
||||
x.{core::List::add}(3);
|
||||
return x;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 1);
|
||||
exp::Expect::equals(#C2, 0);
|
||||
|
@ -102,6 +113,8 @@ static method main() → void {
|
|||
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);
|
||||
}
|
||||
|
||||
constants {
|
||||
|
@ -112,6 +125,8 @@ constants {
|
|||
#C5 = 2
|
||||
#C6 = TypeLiteralConstant(core::int*)
|
||||
#C7 = <core::int*>[#C1, #C5]
|
||||
#C8 = <core::int*>[]
|
||||
#C9 = <core::int*>[#C1]
|
||||
#C8 = 3
|
||||
#C9 = <core::int*>[#C1, #C5, #C8]
|
||||
#C10 = <core::int*>[]
|
||||
#C11 = <core::int*>[#C1]
|
||||
}
|
||||
|
|
|
@ -54,4 +54,11 @@ int getWithIndexExceptionFn3() {
|
|||
return x[0.1];
|
||||
}
|
||||
|
||||
const constListAddException = constListAddExceptionFn();
|
||||
List<int> constListAddExceptionFn() {
|
||||
const List<int> x = [1, 2];
|
||||
x.add(3);
|
||||
return x;
|
||||
}
|
||||
|
||||
void main() {}
|
||||
|
|
|
@ -54,6 +54,13 @@ library /*isNonNullableByDefault*/;
|
|||
// return x[-1];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
|
||||
// const constListAddException = constListAddExceptionFn();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
|
||||
// x.add(3);
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
|
@ -73,6 +80,7 @@ static const field core::int getWithIndexException2 = invalid-expression "Unhand
|
|||
static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
|
||||
return x[0.1];
|
||||
^";
|
||||
static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
|
||||
static method firstExceptionFn() → core::int {
|
||||
return (#C1).{core::Iterable::first};
|
||||
}
|
||||
|
@ -103,6 +111,10 @@ static method getWithIndexExceptionFn3() → core::int {
|
|||
return x[0.1];
|
||||
^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
|
||||
}
|
||||
static method constListAddExceptionFn() → core::List<core::int> {
|
||||
(#C4).{core::List::add}(3);
|
||||
return #C4;
|
||||
}
|
||||
static method main() → void {}
|
||||
|
||||
constants {
|
||||
|
|
|
@ -54,6 +54,13 @@ library /*isNonNullableByDefault*/;
|
|||
// return x[-1];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
|
||||
// const constListAddException = constListAddExceptionFn();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
|
||||
// x.add(3);
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
|
@ -73,6 +80,7 @@ static const field core::int getWithIndexException2 = invalid-expression "Unhand
|
|||
static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
|
||||
return x[0.1];
|
||||
^";
|
||||
static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
|
||||
static method firstExceptionFn() → core::int {
|
||||
return (#C1).{core::Iterable::first};
|
||||
}
|
||||
|
@ -103,6 +111,10 @@ static method getWithIndexExceptionFn3() → core::int {
|
|||
return x[0.1];
|
||||
^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
|
||||
}
|
||||
static method constListAddExceptionFn() → core::List<core::int> {
|
||||
(#C4).{core::List::add}(3);
|
||||
return #C4;
|
||||
}
|
||||
static method main() → void {}
|
||||
|
||||
constants {
|
||||
|
@ -115,4 +127,4 @@ constants {
|
|||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_list_error.dart:48:12 -> IntConstant(-1)
|
||||
Extra constant evaluation: evaluated: 10, effectively constant: 1
|
||||
Extra constant evaluation: evaluated: 11, effectively constant: 1
|
||||
|
|
|
@ -16,4 +16,6 @@ const getWithIndexException2 = getWithIndexExceptionFn2();
|
|||
int getWithIndexExceptionFn2() {}
|
||||
const getWithIndexException3 = getWithIndexExceptionFn3();
|
||||
int getWithIndexExceptionFn3() {}
|
||||
const constListAddException = constListAddExceptionFn();
|
||||
List<int> constListAddExceptionFn() {}
|
||||
void main() {}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
List<int> constListAddExceptionFn() {}
|
||||
const constListAddException = constListAddExceptionFn();
|
||||
const firstException = firstExceptionFn();
|
||||
const getWithIndexException = getWithIndexExceptionFn();
|
||||
const getWithIndexException2 = getWithIndexExceptionFn2();
|
||||
|
|
|
@ -54,6 +54,13 @@ library /*isNonNullableByDefault*/;
|
|||
// return x[-1];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
|
||||
// const constListAddException = constListAddExceptionFn();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
|
||||
// x.add(3);
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
|
@ -73,6 +80,7 @@ static const field core::int getWithIndexException2 = invalid-expression "Unhand
|
|||
static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
|
||||
return x[0.1];
|
||||
^";
|
||||
static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
|
||||
static method firstExceptionFn() → core::int {
|
||||
return (#C1).{core::Iterable::first};
|
||||
}
|
||||
|
@ -103,6 +111,10 @@ static method getWithIndexExceptionFn3() → core::int {
|
|||
return x[0.1];
|
||||
^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
|
||||
}
|
||||
static method constListAddExceptionFn() → core::List<core::int> {
|
||||
(#C4).{core::List::add}(3);
|
||||
return #C4;
|
||||
}
|
||||
static method main() → void {}
|
||||
|
||||
constants {
|
||||
|
|
|
@ -12,6 +12,7 @@ static const field core::int invalidProperty = self::invalidPropertyFn();
|
|||
static const field core::int getWithIndexException = self::getWithIndexExceptionFn();
|
||||
static const field core::int getWithIndexException2 = self::getWithIndexExceptionFn2();
|
||||
static const field core::int getWithIndexException3 = self::getWithIndexExceptionFn3();
|
||||
static const field core::List<core::int> constListAddException = self::constListAddExceptionFn();
|
||||
static method firstExceptionFn() → core::int
|
||||
;
|
||||
static method lastExceptionFn() → core::int
|
||||
|
@ -28,5 +29,7 @@ static method getWithIndexExceptionFn2() → core::int
|
|||
;
|
||||
static method getWithIndexExceptionFn3() → core::int
|
||||
;
|
||||
static method constListAddExceptionFn() → core::List<core::int>
|
||||
;
|
||||
static method main() → void
|
||||
;
|
||||
|
|
|
@ -54,6 +54,13 @@ library /*isNonNullableByDefault*/;
|
|||
// return x[-1];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
|
||||
// const constListAddException = constListAddExceptionFn();
|
||||
// ^
|
||||
// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
|
||||
// x.add(3);
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
|
@ -73,6 +80,7 @@ static const field core::int getWithIndexException2 = invalid-expression "Unhand
|
|||
static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
|
||||
return x[0.1];
|
||||
^";
|
||||
static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
|
||||
static method firstExceptionFn() → core::int {
|
||||
return (#C1).{core::Iterable::first};
|
||||
}
|
||||
|
@ -103,6 +111,10 @@ static method getWithIndexExceptionFn3() → core::int {
|
|||
return x[0.1];
|
||||
^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
|
||||
}
|
||||
static method constListAddExceptionFn() → core::List<core::int> {
|
||||
(#C4).{core::List::add}(3);
|
||||
return #C4;
|
||||
}
|
||||
static method main() → void {}
|
||||
|
||||
constants {
|
||||
|
@ -115,4 +127,4 @@ constants {
|
|||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_list_error.dart:48:12 -> IntConstant(-1)
|
||||
Extra constant evaluation: evaluated: 10, effectively constant: 1
|
||||
Extra constant evaluation: evaluated: 11, effectively constant: 1
|
||||
|
|
|
@ -83,3 +83,13 @@ int getWithIndexExceptionFn3() {
|
|||
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
|
||||
// [cfe] A value of type 'double' can't be assigned to a variable of type 'int'.
|
||||
}
|
||||
|
||||
const constListAddException = constListAddExceptionFn();
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
// [cfe] Constant evaluation error:
|
||||
List<int> constListAddExceptionFn() {
|
||||
const List<int> x = [1, 2];
|
||||
x.add(3);
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -158,6 +158,23 @@ int rangeErrorCatchFn() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
const mutableListVar = mutableList();
|
||||
// ^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
List<int> mutableList() {
|
||||
List<int> x = [1, 2];
|
||||
return x;
|
||||
}
|
||||
|
||||
const mutableListAddVar = mutableListAdd();
|
||||
// ^^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
List<int> mutableListAdd() {
|
||||
List<int> x = [1, 2];
|
||||
x.add(3);
|
||||
return x;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(firstVar, 1);
|
||||
Expect.equals(firstCatchVar, 0);
|
||||
|
@ -173,4 +190,6 @@ void main() {
|
|||
Expect.equals(typeVar, int);
|
||||
Expect.equals(getWithIndexVar, 1);
|
||||
Expect.equals(rangeErrorCatchVar, 0);
|
||||
Expect.equals(mutableListVar, const [1, 2]);
|
||||
Expect.equals(mutableListAddVar, const [1, 2, 3]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue