mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[cfe] Instance method invocations for const functions.
Change-Id: I2e7d8b3859f09dd906e78e6e6d44722a0aabaeb6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196140 Commit-Queue: Kallen Tu <kallentu@google.com> Reviewed-by: Bob Nystrom <rnystrom@google.com> Reviewed-by: Jake Macdonald <jakemac@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
b101a7d002
commit
8a0801572c
11 changed files with 1085 additions and 32 deletions
|
@ -6406,7 +6406,9 @@ class BodyBuilder extends ScopeListener<JumpTarget>
|
|||
{bool isConstantExpression: false,
|
||||
bool isNullAware: false,
|
||||
bool isSuper: false}) {
|
||||
if (constantContext != ConstantContext.none && !isConstantExpression) {
|
||||
if (constantContext != ConstantContext.none &&
|
||||
!isConstantExpression &&
|
||||
!enableConstFunctionsInLibrary) {
|
||||
return buildProblem(
|
||||
fasta.templateNotConstantExpression
|
||||
.withArguments('Method invocation'),
|
||||
|
|
|
@ -1207,7 +1207,10 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
if (env.isEmpty) {
|
||||
// We only try to evaluate the same [node] *once* within an empty
|
||||
// environment.
|
||||
if (nodeCache.containsKey(node)) {
|
||||
// For const functions, recompute getters instead of using the cached
|
||||
// value.
|
||||
bool isGetter = node is InstanceGet || node is PropertyGet;
|
||||
if (nodeCache.containsKey(node) && !(enableConstFunctions && isGetter)) {
|
||||
result = nodeCache[node];
|
||||
if (result == null) {
|
||||
// [null] is a sentinel value only used when still evaluating the same
|
||||
|
@ -2088,9 +2091,17 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
}
|
||||
|
||||
Constant _handleInvocation(
|
||||
Expression node, Name name, Constant receiver, List<Constant> arguments) {
|
||||
Expression node, Name name, Constant receiver, List<Constant> arguments,
|
||||
{List<DartType> typeArguments, Map<String, Constant> namedArguments}) {
|
||||
final String op = name.text;
|
||||
|
||||
// TODO(kallentu): Handle all constant toString methods.
|
||||
if (receiver is PrimitiveConstant &&
|
||||
op == 'toString' &&
|
||||
enableConstFunctions) {
|
||||
return new StringConstant(receiver.value.toString());
|
||||
}
|
||||
|
||||
// Handle == and != first (it's common between all types). Since `a != b` is
|
||||
// parsed as `!(a == b)` it is handled implicitly through ==.
|
||||
if (arguments.length == 1 && op == '==') {
|
||||
|
@ -2262,31 +2273,38 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
}
|
||||
}
|
||||
} else if (receiver is InstanceConstant && enableConstFunctions) {
|
||||
if (arguments.length == 1) {
|
||||
final Constant other = arguments[0];
|
||||
if (receiver.classNode.name == '_ImmutableMap') {
|
||||
switch (op) {
|
||||
case '[]':
|
||||
final ListConstant values = receiver.fieldValues.entries
|
||||
.firstWhere(
|
||||
(entry) => entry.key.canonicalName.name == '_kvPairs',
|
||||
orElse: () => null)
|
||||
.value;
|
||||
assert(values != null);
|
||||
final Class instanceClass = receiver.classNode;
|
||||
assert(typeEnvironment.hierarchy is ClassHierarchy);
|
||||
final Member member = (typeEnvironment.hierarchy as ClassHierarchy)
|
||||
.getDispatchTarget(instanceClass, name);
|
||||
final FunctionNode function = member.function;
|
||||
|
||||
// Each i index element in [values] is a key whose value is the
|
||||
// i+1 index element.
|
||||
int keyIndex = values.entries.indexOf(other);
|
||||
if (keyIndex != -1) {
|
||||
int valueIndex = keyIndex + 1;
|
||||
assert(valueIndex != values.entries.length);
|
||||
return values.entries[valueIndex];
|
||||
} else {
|
||||
// Null value if key is not in the map.
|
||||
return new NullConstant();
|
||||
}
|
||||
// TODO(kallentu): Implement [Object] class methods which have backend
|
||||
// specific functions that cannot be run by the constant evaluator.
|
||||
final bool isObjectMember = member.enclosingClass != null &&
|
||||
member.enclosingClass.name == "Object";
|
||||
if (function != null && !isObjectMember) {
|
||||
return withNewInstanceBuilder(instanceClass, typeArguments, () {
|
||||
final EvaluationEnvironment newEnv = new EvaluationEnvironment();
|
||||
for (int i = 0; i < instanceClass.typeParameters.length; i++) {
|
||||
newEnv.addTypeParameterValue(
|
||||
instanceClass.typeParameters[i], receiver.typeArguments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that fields are visible for instance access.
|
||||
receiver.fieldValues.forEach((Reference fieldRef, Constant value) =>
|
||||
instanceBuilder.setFieldValue(fieldRef.asField, value));
|
||||
return _handleFunctionInvocation(
|
||||
function, receiver.typeArguments, arguments, namedArguments,
|
||||
functionEnvironment: newEnv);
|
||||
});
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case 'toString':
|
||||
// Default value for toString() of instances.
|
||||
return new StringConstant(
|
||||
"Instance of '${receiver.classReference.toStringInternal()}'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2324,7 +2342,7 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
assert(_gotError == null);
|
||||
assert(arguments != null);
|
||||
|
||||
if (enableConstFunctions && receiver is FunctionValue) {
|
||||
if (enableConstFunctions) {
|
||||
// Evaluate type arguments of the method invoked.
|
||||
List<DartType> types = _evaluateTypeArguments(node, node.arguments);
|
||||
if (types == null && _gotError != null) {
|
||||
|
@ -2346,9 +2364,14 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
assert(_gotError == null);
|
||||
assert(named != null);
|
||||
|
||||
return _handleFunctionInvocation(
|
||||
receiver.function, types, arguments, named,
|
||||
functionEnvironment: receiver.environment);
|
||||
if (receiver is FunctionValue) {
|
||||
return _handleFunctionInvocation(
|
||||
receiver.function, types, arguments, named,
|
||||
functionEnvironment: receiver.environment);
|
||||
}
|
||||
|
||||
return _handleInvocation(node, node.name, receiver, arguments,
|
||||
typeArguments: types, namedArguments: named);
|
||||
}
|
||||
|
||||
if (shouldBeUnevaluated) {
|
||||
|
@ -3940,8 +3963,13 @@ class EvaluationEnvironment {
|
|||
}
|
||||
|
||||
DartType substituteType(DartType type) {
|
||||
if (_typeVariables.isEmpty) return type;
|
||||
return substitute(type, _typeVariables);
|
||||
if (_typeVariables.isEmpty) return _parent?.substituteType(type) ?? type;
|
||||
final DartType substitutedType = substitute(type, _typeVariables);
|
||||
if (identical(substitutedType, type) && _parent != null) {
|
||||
// No distinct type created, substitute type in parent.
|
||||
return _parent.substituteType(type);
|
||||
}
|
||||
return substitutedType;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
// 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 invocations of instance functions with const functions.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
|
||||
class B {
|
||||
const B();
|
||||
|
||||
@override
|
||||
String toString() => "B";
|
||||
}
|
||||
|
||||
class C {
|
||||
final int y;
|
||||
|
||||
const C(this.y);
|
||||
|
||||
int fn() {
|
||||
if (y == 1) return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
class D extends C {
|
||||
const D(int y) : super(y);
|
||||
|
||||
@override
|
||||
int fn() => 300;
|
||||
}
|
||||
|
||||
class E extends C {
|
||||
const E(int y) : super(y);
|
||||
}
|
||||
|
||||
class F<T, U, V> {
|
||||
const F();
|
||||
U fn(U x) => x;
|
||||
}
|
||||
|
||||
class G<T> extends F<T, String, num> {
|
||||
const G();
|
||||
}
|
||||
|
||||
const var1 = fn();
|
||||
String fn() => const A().toString();
|
||||
|
||||
const toString1 = const A().toString();
|
||||
|
||||
const var2 = fn2();
|
||||
String fn2() => const B().toString();
|
||||
|
||||
const toString2 = const B().toString();
|
||||
|
||||
const var3 = fn3();
|
||||
const var4 = fn4();
|
||||
int fn3() => const C(0).fn();
|
||||
int fn4() => const C(1).fn();
|
||||
|
||||
const fnVal1 = const C(0).fn();
|
||||
const fnVal2 = const C(1).fn();
|
||||
|
||||
const var5 = fn5();
|
||||
int fn5() => const D(1).fn();
|
||||
|
||||
const fnVal3 = const D(1).fn();
|
||||
|
||||
const var6 = fn6();
|
||||
int fn6() => const E(1).fn();
|
||||
|
||||
const fnVal4 = const E(0).fn();
|
||||
|
||||
const var7 = fn7();
|
||||
String fn7() => const F<int, String, num>().fn("string");
|
||||
|
||||
const fnVal5 = const F<int, String, num>().fn("string");
|
||||
|
||||
const var8 = fn8();
|
||||
String fn8() => const G<int>().fn("string");
|
||||
|
||||
const fnVal6 = const G<int>().fn("string");
|
||||
|
||||
void main() {
|
||||
Expect.equals(var1, const A().toString());
|
||||
Expect.equals(toString1, const A().toString());
|
||||
Expect.equals(var2, const B().toString());
|
||||
Expect.equals(toString2, const B().toString());
|
||||
Expect.equals(var3, 200);
|
||||
Expect.equals(var4, 100);
|
||||
Expect.equals(fnVal1, 200);
|
||||
Expect.equals(fnVal2, 100);
|
||||
Expect.equals(var5, 300);
|
||||
Expect.equals(fnVal3, 300);
|
||||
Expect.equals(var6, 100);
|
||||
Expect.equals(fnVal4, 200);
|
||||
Expect.equals(var7, "string");
|
||||
Expect.equals(fnVal5, "string");
|
||||
Expect.equals(var8, "string");
|
||||
Expect.equals(fnVal6, "string");
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
class B extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
@#C1
|
||||
method toString() → core::String
|
||||
return "B";
|
||||
}
|
||||
class C extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int y;
|
||||
const constructor •(core::int y) → self::C
|
||||
: self::C::y = y, super core::Object::•()
|
||||
;
|
||||
method fn() → core::int {
|
||||
if(this.{self::C::y}.{core::num::==}(1))
|
||||
return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
class D extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::D
|
||||
: super self::C::•(y)
|
||||
;
|
||||
@#C1
|
||||
method fn() → core::int
|
||||
return 300;
|
||||
}
|
||||
class E extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::E
|
||||
: super self::C::•(y)
|
||||
;
|
||||
}
|
||||
class F<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::F<self::F::T%, self::F::U%, self::F::V%>
|
||||
: super core::Object::•()
|
||||
;
|
||||
method fn(generic-covariant-impl self::F::U% x) → self::F::U%
|
||||
return x;
|
||||
}
|
||||
class G<T extends core::Object? = dynamic> extends self::F<self::G::T%, core::String, core::num> /*hasConstConstructor*/ {
|
||||
const constructor •() → self::G<self::G::T%>
|
||||
: super self::F::•()
|
||||
;
|
||||
}
|
||||
static const field core::String var1 = #C2;
|
||||
static const field core::String toString1 = #C2;
|
||||
static const field core::String var2 = #C3;
|
||||
static const field core::String toString2 = #C3;
|
||||
static const field core::int var3 = #C4;
|
||||
static const field core::int var4 = #C5;
|
||||
static const field core::int fnVal1 = #C4;
|
||||
static const field core::int fnVal2 = #C5;
|
||||
static const field core::int var5 = #C6;
|
||||
static const field core::int fnVal3 = #C6;
|
||||
static const field core::int var6 = #C5;
|
||||
static const field core::int fnVal4 = #C4;
|
||||
static const field core::String var7 = #C7;
|
||||
static const field core::String fnVal5 = #C7;
|
||||
static const field core::String var8 = #C7;
|
||||
static const field core::String fnVal6 = #C7;
|
||||
static method fn() → core::String
|
||||
return (#C8).{core::Object::toString}();
|
||||
static method fn2() → core::String
|
||||
return (#C9).{self::B::toString}();
|
||||
static method fn3() → core::int
|
||||
return (#C11).{self::C::fn}();
|
||||
static method fn4() → core::int
|
||||
return (#C13).{self::C::fn}();
|
||||
static method fn5() → core::int
|
||||
return (#C14).{self::D::fn}();
|
||||
static method fn6() → core::int
|
||||
return (#C15).{self::C::fn}();
|
||||
static method fn7() → core::String
|
||||
return (#C16).{self::F::fn}("string");
|
||||
static method fn8() → core::String
|
||||
return (#C17).{self::F::fn}("string");
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = core::_Override {}
|
||||
#C2 = "Instance of 'A'"
|
||||
#C3 = "B"
|
||||
#C4 = 200
|
||||
#C5 = 100
|
||||
#C6 = 300
|
||||
#C7 = "string"
|
||||
#C8 = self::A {}
|
||||
#C9 = self::B {}
|
||||
#C10 = 0
|
||||
#C11 = self::C {y:#C10}
|
||||
#C12 = 1
|
||||
#C13 = self::C {y:#C12}
|
||||
#C14 = self::D {y:#C12}
|
||||
#C15 = self::E {y:#C12}
|
||||
#C16 = self::F<core::int, core::String, core::num> {}
|
||||
#C17 = self::G<core::int> {}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_instance_methods.dart:
|
||||
- A. (from org-dartlang-testcase:///const_functions_instance_methods.dart:10:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
- B. (from org-dartlang-testcase:///const_functions_instance_methods.dart:14:9)
|
||||
- C. (from org-dartlang-testcase:///const_functions_instance_methods.dart:23:9)
|
||||
- D. (from org-dartlang-testcase:///const_functions_instance_methods.dart:32:9)
|
||||
- E. (from org-dartlang-testcase:///const_functions_instance_methods.dart:39:9)
|
||||
- F. (from org-dartlang-testcase:///const_functions_instance_methods.dart:43:9)
|
||||
- G. (from org-dartlang-testcase:///const_functions_instance_methods.dart:48:9)
|
|
@ -0,0 +1,138 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
class B extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
@#C1
|
||||
method toString() → core::String
|
||||
return "B";
|
||||
}
|
||||
class C extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int y;
|
||||
const constructor •(core::int y) → self::C
|
||||
: self::C::y = y, super core::Object::•()
|
||||
;
|
||||
method fn() → core::int {
|
||||
if(this.{self::C::y}.{core::num::==}(1))
|
||||
return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
class D extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::D
|
||||
: super self::C::•(y)
|
||||
;
|
||||
@#C1
|
||||
method fn() → core::int
|
||||
return 300;
|
||||
}
|
||||
class E extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::E
|
||||
: super self::C::•(y)
|
||||
;
|
||||
}
|
||||
class F<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::F<self::F::T%, self::F::U%, self::F::V%>
|
||||
: super core::Object::•()
|
||||
;
|
||||
method fn(generic-covariant-impl self::F::U% x) → self::F::U%
|
||||
return x;
|
||||
}
|
||||
class G<T extends core::Object? = dynamic> extends self::F<self::G::T%, core::String, core::num> /*hasConstConstructor*/ {
|
||||
const constructor •() → self::G<self::G::T%>
|
||||
: super self::F::•()
|
||||
;
|
||||
}
|
||||
static const field core::String var1 = #C2;
|
||||
static const field core::String toString1 = #C2;
|
||||
static const field core::String var2 = #C3;
|
||||
static const field core::String toString2 = #C3;
|
||||
static const field core::int var3 = #C4;
|
||||
static const field core::int var4 = #C5;
|
||||
static const field core::int fnVal1 = #C4;
|
||||
static const field core::int fnVal2 = #C5;
|
||||
static const field core::int var5 = #C6;
|
||||
static const field core::int fnVal3 = #C6;
|
||||
static const field core::int var6 = #C5;
|
||||
static const field core::int fnVal4 = #C4;
|
||||
static const field core::String var7 = #C7;
|
||||
static const field core::String fnVal5 = #C7;
|
||||
static const field core::String var8 = #C7;
|
||||
static const field core::String fnVal6 = #C7;
|
||||
static method fn() → core::String
|
||||
return (#C8).{core::Object::toString}();
|
||||
static method fn2() → core::String
|
||||
return (#C9).{self::B::toString}();
|
||||
static method fn3() → core::int
|
||||
return (#C11).{self::C::fn}();
|
||||
static method fn4() → core::int
|
||||
return (#C13).{self::C::fn}();
|
||||
static method fn5() → core::int
|
||||
return (#C14).{self::D::fn}();
|
||||
static method fn6() → core::int
|
||||
return (#C15).{self::C::fn}();
|
||||
static method fn7() → core::String
|
||||
return (#C16).{self::F::fn}("string");
|
||||
static method fn8() → core::String
|
||||
return (#C17).{self::F::fn}("string");
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = core::_Override {}
|
||||
#C2 = "Instance of 'A'"
|
||||
#C3 = "B"
|
||||
#C4 = 200
|
||||
#C5 = 100
|
||||
#C6 = 300
|
||||
#C7 = "string"
|
||||
#C8 = self::A {}
|
||||
#C9 = self::B {}
|
||||
#C10 = 0
|
||||
#C11 = self::C {y:#C10}
|
||||
#C12 = 1
|
||||
#C13 = self::C {y:#C12}
|
||||
#C14 = self::D {y:#C12}
|
||||
#C15 = self::E {y:#C12}
|
||||
#C16 = self::F<core::int, core::String, core::num> {}
|
||||
#C17 = self::G<core::int> {}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_instance_methods.dart:
|
||||
- A. (from org-dartlang-testcase:///const_functions_instance_methods.dart:10:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
- B. (from org-dartlang-testcase:///const_functions_instance_methods.dart:14:9)
|
||||
- C. (from org-dartlang-testcase:///const_functions_instance_methods.dart:23:9)
|
||||
- D. (from org-dartlang-testcase:///const_functions_instance_methods.dart:32:9)
|
||||
- E. (from org-dartlang-testcase:///const_functions_instance_methods.dart:39:9)
|
||||
- F. (from org-dartlang-testcase:///const_functions_instance_methods.dart:43:9)
|
||||
- G. (from org-dartlang-testcase:///const_functions_instance_methods.dart:48:9)
|
|
@ -0,0 +1,62 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
|
||||
class B {
|
||||
const B();
|
||||
@override
|
||||
String toString() => "B";
|
||||
}
|
||||
|
||||
class C {
|
||||
final int y;
|
||||
const C(this.y);
|
||||
int fn() {}
|
||||
}
|
||||
|
||||
class D extends C {
|
||||
const D(int y) : super(y);
|
||||
@override
|
||||
int fn() => 300;
|
||||
}
|
||||
|
||||
class E extends C {
|
||||
const E(int y) : super(y);
|
||||
}
|
||||
|
||||
class F<T, U, V> {
|
||||
const F();
|
||||
U fn(U x) => x;
|
||||
}
|
||||
|
||||
class G<T> extends F<T, String, num> {
|
||||
const G();
|
||||
}
|
||||
|
||||
const var1 = fn();
|
||||
String fn() => const A().toString();
|
||||
const toString1 = const A().toString();
|
||||
const var2 = fn2();
|
||||
String fn2() => const B().toString();
|
||||
const toString2 = const B().toString();
|
||||
const var3 = fn3();
|
||||
const var4 = fn4();
|
||||
int fn3() => const C(0).fn();
|
||||
int fn4() => const C(1).fn();
|
||||
const fnVal1 = const C(0).fn();
|
||||
const fnVal2 = const C(1).fn();
|
||||
const var5 = fn5();
|
||||
int fn5() => const D(1).fn();
|
||||
const fnVal3 = const D(1).fn();
|
||||
const var6 = fn6();
|
||||
int fn6() => const E(1).fn();
|
||||
const fnVal4 = const E(0).fn();
|
||||
const var7 = fn7();
|
||||
String fn7() => const F<int, String, num>().fn("string");
|
||||
const fnVal5 = const F<int, String, num>().fn("string");
|
||||
const var8 = fn8();
|
||||
String fn8() => const G<int>().fn("string");
|
||||
const fnVal6 = const G<int>().fn("string");
|
||||
void main() {}
|
|
@ -0,0 +1,63 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
String fn() => const A().toString();
|
||||
String fn2() => const B().toString();
|
||||
String fn7() => const F<int, String, num>().fn("string");
|
||||
String fn8() => const G<int>().fn("string");
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
|
||||
class B {
|
||||
@override
|
||||
String toString() => "B";
|
||||
const B();
|
||||
}
|
||||
|
||||
class C {
|
||||
const C(this.y);
|
||||
final int y;
|
||||
int fn() {}
|
||||
}
|
||||
|
||||
class D extends C {
|
||||
const D(int y) : super(y);
|
||||
@override
|
||||
int fn() => 300;
|
||||
}
|
||||
|
||||
class E extends C {
|
||||
const E(int y) : super(y);
|
||||
}
|
||||
|
||||
class F<T, U, V> {
|
||||
U fn(U x) => x;
|
||||
const F();
|
||||
}
|
||||
|
||||
class G<T> extends F<T, String, num> {
|
||||
const G();
|
||||
}
|
||||
|
||||
const fnVal1 = const C(0).fn();
|
||||
const fnVal2 = const C(1).fn();
|
||||
const fnVal3 = const D(1).fn();
|
||||
const fnVal4 = const E(0).fn();
|
||||
const fnVal5 = const F<int, String, num>().fn("string");
|
||||
const fnVal6 = const G<int>().fn("string");
|
||||
const toString1 = const A().toString();
|
||||
const toString2 = const B().toString();
|
||||
const var1 = fn();
|
||||
const var2 = fn2();
|
||||
const var3 = fn3();
|
||||
const var4 = fn4();
|
||||
const var5 = fn5();
|
||||
const var6 = fn6();
|
||||
const var7 = fn7();
|
||||
const var8 = fn8();
|
||||
int fn3() => const C(0).fn();
|
||||
int fn4() => const C(1).fn();
|
||||
int fn5() => const D(1).fn();
|
||||
int fn6() => const E(1).fn();
|
||||
void main() {}
|
|
@ -0,0 +1,138 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
class B extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
@#C1
|
||||
method toString() → core::String
|
||||
return "B";
|
||||
}
|
||||
class C extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int y;
|
||||
const constructor •(core::int y) → self::C
|
||||
: self::C::y = y, super core::Object::•()
|
||||
;
|
||||
method fn() → core::int {
|
||||
if(this.{self::C::y}.{core::num::==}(1))
|
||||
return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
class D extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::D
|
||||
: super self::C::•(y)
|
||||
;
|
||||
@#C1
|
||||
method fn() → core::int
|
||||
return 300;
|
||||
}
|
||||
class E extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::E
|
||||
: super self::C::•(y)
|
||||
;
|
||||
}
|
||||
class F<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::F<self::F::T%, self::F::U%, self::F::V%>
|
||||
: super core::Object::•()
|
||||
;
|
||||
method fn(generic-covariant-impl self::F::U% x) → self::F::U%
|
||||
return x;
|
||||
}
|
||||
class G<T extends core::Object? = dynamic> extends self::F<self::G::T%, core::String, core::num> /*hasConstConstructor*/ {
|
||||
const constructor •() → self::G<self::G::T%>
|
||||
: super self::F::•()
|
||||
;
|
||||
}
|
||||
static const field core::String var1 = #C2;
|
||||
static const field core::String toString1 = #C2;
|
||||
static const field core::String var2 = #C3;
|
||||
static const field core::String toString2 = #C3;
|
||||
static const field core::int var3 = #C4;
|
||||
static const field core::int var4 = #C5;
|
||||
static const field core::int fnVal1 = #C4;
|
||||
static const field core::int fnVal2 = #C5;
|
||||
static const field core::int var5 = #C6;
|
||||
static const field core::int fnVal3 = #C6;
|
||||
static const field core::int var6 = #C5;
|
||||
static const field core::int fnVal4 = #C4;
|
||||
static const field core::String var7 = #C7;
|
||||
static const field core::String fnVal5 = #C7;
|
||||
static const field core::String var8 = #C7;
|
||||
static const field core::String fnVal6 = #C7;
|
||||
static method fn() → core::String
|
||||
return (#C8).{core::Object::toString}();
|
||||
static method fn2() → core::String
|
||||
return (#C9).{self::B::toString}();
|
||||
static method fn3() → core::int
|
||||
return (#C11).{self::C::fn}();
|
||||
static method fn4() → core::int
|
||||
return (#C13).{self::C::fn}();
|
||||
static method fn5() → core::int
|
||||
return (#C14).{self::D::fn}();
|
||||
static method fn6() → core::int
|
||||
return (#C15).{self::C::fn}();
|
||||
static method fn7() → core::String
|
||||
return (#C16).{self::F::fn}("string");
|
||||
static method fn8() → core::String
|
||||
return (#C17).{self::F::fn}("string");
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = core::_Override {}
|
||||
#C2 = "Instance of 'A'"
|
||||
#C3 = "B"
|
||||
#C4 = 200
|
||||
#C5 = 100
|
||||
#C6 = 300
|
||||
#C7 = "string"
|
||||
#C8 = self::A {}
|
||||
#C9 = self::B {}
|
||||
#C10 = 0
|
||||
#C11 = self::C {y:#C10}
|
||||
#C12 = 1
|
||||
#C13 = self::C {y:#C12}
|
||||
#C14 = self::D {y:#C12}
|
||||
#C15 = self::E {y:#C12}
|
||||
#C16 = self::F<core::int*, core::String*, core::num*> {}
|
||||
#C17 = self::G<core::int*> {}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_instance_methods.dart:
|
||||
- A. (from org-dartlang-testcase:///const_functions_instance_methods.dart:10:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
- B. (from org-dartlang-testcase:///const_functions_instance_methods.dart:14:9)
|
||||
- C. (from org-dartlang-testcase:///const_functions_instance_methods.dart:23:9)
|
||||
- D. (from org-dartlang-testcase:///const_functions_instance_methods.dart:32:9)
|
||||
- E. (from org-dartlang-testcase:///const_functions_instance_methods.dart:39:9)
|
||||
- F. (from org-dartlang-testcase:///const_functions_instance_methods.dart:43:9)
|
||||
- G. (from org-dartlang-testcase:///const_functions_instance_methods.dart:48:9)
|
|
@ -0,0 +1,100 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
class B extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
@core::override
|
||||
method toString() → core::String
|
||||
;
|
||||
}
|
||||
class C extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int y;
|
||||
const constructor •(core::int y) → self::C
|
||||
: self::C::y = y, super core::Object::•()
|
||||
;
|
||||
method fn() → core::int
|
||||
;
|
||||
}
|
||||
class D extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::D
|
||||
: super self::C::•(y)
|
||||
;
|
||||
@core::override
|
||||
method fn() → core::int
|
||||
;
|
||||
}
|
||||
class E extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::E
|
||||
: super self::C::•(y)
|
||||
;
|
||||
}
|
||||
class F<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::F<self::F::T%, self::F::U%, self::F::V%>
|
||||
: super core::Object::•()
|
||||
;
|
||||
method fn(generic-covariant-impl self::F::U% x) → self::F::U%
|
||||
;
|
||||
}
|
||||
class G<T extends core::Object? = dynamic> extends self::F<self::G::T%, core::String, core::num> /*hasConstConstructor*/ {
|
||||
const constructor •() → self::G<self::G::T%>
|
||||
: super self::F::•()
|
||||
;
|
||||
}
|
||||
static const field core::String var1 = self::fn();
|
||||
static const field core::String toString1 = const self::A::•().{core::Object::toString}();
|
||||
static const field core::String var2 = self::fn2();
|
||||
static const field core::String toString2 = const self::B::•().{self::B::toString}();
|
||||
static const field core::int var3 = self::fn3();
|
||||
static const field core::int var4 = self::fn4();
|
||||
static const field core::int fnVal1 = const self::C::•(0).{self::C::fn}();
|
||||
static const field core::int fnVal2 = const self::C::•(1).{self::C::fn}();
|
||||
static const field core::int var5 = self::fn5();
|
||||
static const field core::int fnVal3 = const self::D::•(1).{self::D::fn}();
|
||||
static const field core::int var6 = self::fn6();
|
||||
static const field core::int fnVal4 = const self::E::•(0).{self::C::fn}();
|
||||
static const field core::String var7 = self::fn7();
|
||||
static const field core::String fnVal5 = const self::F::•<core::int, core::String, core::num>().{self::F::fn}("string");
|
||||
static const field core::String var8 = self::fn8();
|
||||
static const field core::String fnVal6 = const self::G::•<core::int>().{self::F::fn}("string");
|
||||
static method fn() → core::String
|
||||
;
|
||||
static method fn2() → core::String
|
||||
;
|
||||
static method fn3() → core::int
|
||||
;
|
||||
static method fn4() → core::int
|
||||
;
|
||||
static method fn5() → core::int
|
||||
;
|
||||
static method fn6() → core::int
|
||||
;
|
||||
static method fn7() → core::String
|
||||
;
|
||||
static method fn8() → core::String
|
||||
;
|
||||
static method main() → void
|
||||
;
|
||||
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_instance_methods.dart:16:4 -> InstanceConstant(const _Override{})
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///const_functions_instance_methods.dart:34:4 -> InstanceConstant(const _Override{})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:54:25 -> InstanceConstant(const A{})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:59:25 -> InstanceConstant(const B{})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:66:22 -> InstanceConstant(const C{C.y: 0})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:67:22 -> InstanceConstant(const C{C.y: 1})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:72:22 -> InstanceConstant(const D{C.y: 1})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:77:22 -> InstanceConstant(const E{C.y: 0})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:82:22 -> InstanceConstant(const F<int*, String*, num*>{})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_instance_methods.dart:87:22 -> InstanceConstant(const G<int*>{})
|
||||
Extra constant evaluation: evaluated: 29, effectively constant: 10
|
|
@ -0,0 +1,138 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
class B extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
@#C1
|
||||
method toString() → core::String
|
||||
return "B";
|
||||
}
|
||||
class C extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int y;
|
||||
const constructor •(core::int y) → self::C
|
||||
: self::C::y = y, super core::Object::•()
|
||||
;
|
||||
method fn() → core::int {
|
||||
if(this.{self::C::y}.{core::num::==}(1))
|
||||
return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
class D extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::D
|
||||
: super self::C::•(y)
|
||||
;
|
||||
@#C1
|
||||
method fn() → core::int
|
||||
return 300;
|
||||
}
|
||||
class E extends self::C /*hasConstConstructor*/ {
|
||||
const constructor •(core::int y) → self::E
|
||||
: super self::C::•(y)
|
||||
;
|
||||
}
|
||||
class F<T extends core::Object? = dynamic, U extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
|
||||
const constructor •() → self::F<self::F::T%, self::F::U%, self::F::V%>
|
||||
: super core::Object::•()
|
||||
;
|
||||
method fn(generic-covariant-impl self::F::U% x) → self::F::U%
|
||||
return x;
|
||||
}
|
||||
class G<T extends core::Object? = dynamic> extends self::F<self::G::T%, core::String, core::num> /*hasConstConstructor*/ {
|
||||
const constructor •() → self::G<self::G::T%>
|
||||
: super self::F::•()
|
||||
;
|
||||
}
|
||||
static const field core::String var1 = #C2;
|
||||
static const field core::String toString1 = #C2;
|
||||
static const field core::String var2 = #C3;
|
||||
static const field core::String toString2 = #C3;
|
||||
static const field core::int var3 = #C4;
|
||||
static const field core::int var4 = #C5;
|
||||
static const field core::int fnVal1 = #C4;
|
||||
static const field core::int fnVal2 = #C5;
|
||||
static const field core::int var5 = #C6;
|
||||
static const field core::int fnVal3 = #C6;
|
||||
static const field core::int var6 = #C5;
|
||||
static const field core::int fnVal4 = #C4;
|
||||
static const field core::String var7 = #C7;
|
||||
static const field core::String fnVal5 = #C7;
|
||||
static const field core::String var8 = #C7;
|
||||
static const field core::String fnVal6 = #C7;
|
||||
static method fn() → core::String
|
||||
return (#C8).{core::Object::toString}();
|
||||
static method fn2() → core::String
|
||||
return (#C9).{self::B::toString}();
|
||||
static method fn3() → core::int
|
||||
return (#C11).{self::C::fn}();
|
||||
static method fn4() → core::int
|
||||
return (#C13).{self::C::fn}();
|
||||
static method fn5() → core::int
|
||||
return (#C14).{self::D::fn}();
|
||||
static method fn6() → core::int
|
||||
return (#C15).{self::C::fn}();
|
||||
static method fn7() → core::String
|
||||
return (#C16).{self::F::fn}("string");
|
||||
static method fn8() → core::String
|
||||
return (#C17).{self::F::fn}("string");
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C2, (#C8).{core::Object::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C3, (#C9).{self::B::toString}());
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C6, 300);
|
||||
exp::Expect::equals(#C5, 100);
|
||||
exp::Expect::equals(#C4, 200);
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
exp::Expect::equals(#C7, "string");
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = core::_Override {}
|
||||
#C2 = "Instance of 'A'"
|
||||
#C3 = "B"
|
||||
#C4 = 200
|
||||
#C5 = 100
|
||||
#C6 = 300
|
||||
#C7 = "string"
|
||||
#C8 = self::A {}
|
||||
#C9 = self::B {}
|
||||
#C10 = 0
|
||||
#C11 = self::C {y:#C10}
|
||||
#C12 = 1
|
||||
#C13 = self::C {y:#C12}
|
||||
#C14 = self::D {y:#C12}
|
||||
#C15 = self::E {y:#C12}
|
||||
#C16 = self::F<core::int*, core::String*, core::num*> {}
|
||||
#C17 = self::G<core::int*> {}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_instance_methods.dart:
|
||||
- A. (from org-dartlang-testcase:///const_functions_instance_methods.dart:10:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
- B. (from org-dartlang-testcase:///const_functions_instance_methods.dart:14:9)
|
||||
- C. (from org-dartlang-testcase:///const_functions_instance_methods.dart:23:9)
|
||||
- D. (from org-dartlang-testcase:///const_functions_instance_methods.dart:32:9)
|
||||
- E. (from org-dartlang-testcase:///const_functions_instance_methods.dart:39:9)
|
||||
- F. (from org-dartlang-testcase:///const_functions_instance_methods.dart:43:9)
|
||||
- G. (from org-dartlang-testcase:///const_functions_instance_methods.dart:48:9)
|
|
@ -0,0 +1,140 @@
|
|||
// 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 invocations of instance functions with const functions.
|
||||
|
||||
// SharedOptions=--enable-experiment=const-functions
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
|
||||
class B {
|
||||
const B();
|
||||
|
||||
@override
|
||||
String toString() => "B";
|
||||
}
|
||||
|
||||
class C {
|
||||
final int y;
|
||||
|
||||
const C(this.y);
|
||||
|
||||
int fn() {
|
||||
if (y == 1) return 100;
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
class D extends C {
|
||||
const D(int y) : super(y);
|
||||
|
||||
@override
|
||||
int fn() => 300;
|
||||
}
|
||||
|
||||
class E extends C {
|
||||
const E(int y) : super(y);
|
||||
}
|
||||
|
||||
class F<T, U, V> {
|
||||
const F();
|
||||
U fn(U x) => x;
|
||||
}
|
||||
|
||||
class G<T> extends F<T, String, num> {
|
||||
const G();
|
||||
}
|
||||
|
||||
const var1 = fn();
|
||||
// ^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
String fn() => const A().toString();
|
||||
|
||||
const toString1 = const A().toString();
|
||||
// ^^^^^^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
const var2 = fn2();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
String fn2() => const B().toString();
|
||||
|
||||
const toString2 = const B().toString();
|
||||
// ^^^^^^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
const var3 = fn3();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
const var4 = fn4();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn3() => const C(0).fn();
|
||||
int fn4() => const C(1).fn();
|
||||
|
||||
const fnVal1 = const C(0).fn();
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
const fnVal2 = const C(1).fn();
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
const var5 = fn5();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn5() => const D(1).fn();
|
||||
|
||||
const fnVal3 = const D(1).fn();
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
const var6 = fn6();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn6() => const E(1).fn();
|
||||
|
||||
const fnVal4 = const E(0).fn();
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
const var7 = fn7();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
String fn7() => const F<int, String, num>().fn("string");
|
||||
|
||||
const fnVal5 = const F<int, String, num>().fn("string");
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
const var8 = fn8();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
String fn8() => const G<int>().fn("string");
|
||||
|
||||
const fnVal6 = const G<int>().fn("string");
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
|
||||
void main() {
|
||||
Expect.equals(var1, const A().toString());
|
||||
Expect.equals(toString1, const A().toString());
|
||||
Expect.equals(var2, const B().toString());
|
||||
Expect.equals(toString2, const B().toString());
|
||||
Expect.equals(var3, 200);
|
||||
Expect.equals(var4, 100);
|
||||
Expect.equals(fnVal1, 200);
|
||||
Expect.equals(fnVal2, 100);
|
||||
Expect.equals(var5, 300);
|
||||
Expect.equals(fnVal3, 300);
|
||||
Expect.equals(var6, 100);
|
||||
Expect.equals(fnVal4, 200);
|
||||
Expect.equals(var7, "string");
|
||||
Expect.equals(fnVal5, "string");
|
||||
Expect.equals(var8, "string");
|
||||
Expect.equals(fnVal6, "string");
|
||||
}
|
Loading…
Reference in a new issue