[cfe] Allow non-const constructor invocations in const functions.

Change-Id: Ieb8d3030c6132ccf9037e64cef3ba6c4eeaa90ea
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/197180
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
Kallen Tu 2021-04-28 21:17:33 +00:00 committed by commit-bot@chromium.org
parent 83a957f9bd
commit 4e2fac951d
17 changed files with 123 additions and 2 deletions

View file

@ -1444,7 +1444,7 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
@override
Constant visitConstructorInvocation(ConstructorInvocation node) {
if (!node.isConst) {
if (!node.isConst && !enableConstFunctions) {
return createInvalidExpressionConstant(
node, 'Non-constant constructor invocation "$node".');
}

View file

@ -23,6 +23,9 @@ class A {
}
}
const var3 = fn();
A fn() => A();
void main() {
Expect.equals(var1.name, printString);
}

View file

@ -21,6 +21,9 @@ class A extends core::Object /*hasConstConstructor*/ {
static const field core::String printString = #C1;
static const field self::Simple var1 = #C2;
static const field self::A var2 = #C3;
static const field self::A var3 = #C3;
static method fn() → self::A
return new self::A::•();
static method main() → void {
exp::Expect::equals((#C2).{self::Simple::name}, #C1);
}

View file

@ -21,6 +21,9 @@ class A extends core::Object /*hasConstConstructor*/ {
static const field core::String printString = #C1;
static const field self::Simple var1 = #C2;
static const field self::A var2 = #C3;
static const field self::A var3 = #C3;
static method fn() → self::A
return new self::A::•();
static method main() → void {
exp::Expect::equals((#C2).{self::Simple::name}, #C1);
}

View file

@ -9,4 +9,6 @@ const var2 = A();
class A {
const A() {}
}
const var3 = fn();
A fn() => A();
void main() {}

View file

@ -21,6 +21,9 @@ class A extends core::Object /*hasConstConstructor*/ {
static const field core::String printString = #C1;
static const field self::Simple var1 = #C2;
static const field self::A var2 = #C3;
static const field self::A var3 = #C3;
static method fn() → self::A
return new self::A::•();
static method main() → void {
exp::Expect::equals((#C2).{self::Simple::name}, #C1);
}

View file

@ -18,6 +18,9 @@ class A extends core::Object /*hasConstConstructor*/ {
static const field core::String printString = "print";
static const field self::Simple var1 = const self::Simple::•(self::printString);
static const field self::A var2 = const self::A::•();
static const field self::A var3 = self::fn();
static method fn() → self::A
;
static method main() → void
;
@ -25,4 +28,4 @@ static method main() → void
Extra constant evaluation status:
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_const_ctor.dart:10:14 -> InstanceConstant(const Simple{Simple.name: "print"})
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_const_ctor.dart:19:14 -> InstanceConstant(const A{})
Extra constant evaluation: evaluated: 3, effectively constant: 2
Extra constant evaluation: evaluated: 4, effectively constant: 2

View file

@ -21,6 +21,9 @@ class A extends core::Object /*hasConstConstructor*/ {
static const field core::String printString = #C1;
static const field self::Simple var1 = #C2;
static const field self::A var2 = #C3;
static const field self::A var3 = #C3;
static method fn() → self::A
return new self::A::•();
static method main() → void {
exp::Expect::equals((#C2).{self::Simple::name}, #C1);
}

View file

@ -38,4 +38,9 @@ class B extends A {
const B() : super();
}
const var4 = C();
class C {
int? x;
}
void main() {}

View file

@ -2,6 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// Try using a constructor or factory that is 'const'.
// const var4 = C();
// ^
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
// Try removing the return type.
// return Simple2(this.name);
@ -60,6 +65,12 @@ class B extends self::A /*hasConstConstructor*/ {
: super self::A::•()
;
}
class C extends core::Object {
field core::int? x = null;
synthetic constructor •() → self::C
: super core::Object::•()
;
}
static const field core::String printString = #C1;
static const field self::Simple var1 = invalid-expression "This assertion failed.";
static const field self::Simple2 var2 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
@ -67,6 +78,10 @@ Try removing the return type.
return Simple2(this.name);
^";
static const field self::B var3 = invalid-expression "This assertion failed.";
static const field dynamic var4 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
const var4 = C();
^";
static method main() → void {}
constants {

View file

@ -2,6 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// Try using a constructor or factory that is 'const'.
// const var4 = C();
// ^
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
// Try removing the return type.
// return Simple2(this.name);
@ -60,6 +65,12 @@ class B extends self::A /*hasConstConstructor*/ {
: super self::A::•()
;
}
class C extends core::Object {
field core::int? x = null;
synthetic constructor •() → self::C
: super core::Object::•()
;
}
static const field core::String printString = #C1;
static const field self::Simple var1 = invalid-expression "This assertion failed.";
static const field self::Simple2 var2 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
@ -67,6 +78,10 @@ Try removing the return type.
return Simple2(this.name);
^";
static const field self::B var3 = invalid-expression "This assertion failed.";
static const field dynamic var4 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
const var4 = C();
^";
static method main() → void {}
constants {

View file

@ -17,4 +17,8 @@ class A {
class B extends A {
const B() : super();
}
const var4 = C();
class C {
int? x;
}
void main() {}

View file

@ -2,6 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// Try using a constructor or factory that is 'const'.
// const var4 = C();
// ^
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
// Try removing the return type.
// return Simple2(this.name);
@ -60,6 +65,12 @@ class B extends self::A /*hasConstConstructor*/ {
: super self::A::•()
;
}
class C extends core::Object {
field core::int? x = null;
synthetic constructor •() → self::C
: super core::Object::•()
;
}
static const field core::String printString = #C1;
static const field self::Simple var1 = invalid-expression "This assertion failed.";
static const field self::Simple2 var2 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
@ -67,6 +78,10 @@ Try removing the return type.
return Simple2(this.name);
^";
static const field self::B var3 = invalid-expression "This assertion failed.";
static const field dynamic var4 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
const var4 = C();
^";
static method main() → void {}
constants {

View file

@ -1,4 +1,12 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// Try using a constructor or factory that is 'const'.
// const var4 = C();
// ^
//
import self as self;
import "dart:core" as core;
@ -26,10 +34,19 @@ class B extends self::A /*hasConstConstructor*/ {
: super self::A::•()
;
}
class C extends core::Object {
field core::int? x;
synthetic constructor •() → self::C
;
}
static const field core::String printString = "print";
static const field self::Simple var1 = const self::Simple::•(self::printString);
static const field self::Simple2 var2 = const self::Simple2::•(self::printString);
static const field self::B var3 = const self::B::•();
static const field dynamic var4 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
const var4 = C();
^";
static method main() → void
;

View file

@ -2,6 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// Try using a constructor or factory that is 'const'.
// const var4 = C();
// ^
//
// pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
// Try removing the return type.
// return Simple2(this.name);
@ -60,6 +65,12 @@ class B extends self::A /*hasConstConstructor*/ {
: super self::A::•()
;
}
class C extends core::Object {
field core::int? x = null;
synthetic constructor •() → self::C
: super core::Object::•()
;
}
static const field core::String printString = #C1;
static const field self::Simple var1 = invalid-expression "This assertion failed.";
static const field self::Simple2 var2 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:26:5: Error: Constructors can't have a return type.
@ -67,6 +78,10 @@ Try removing the return type.
return Simple2(this.name);
^";
static const field self::B var3 = invalid-expression "This assertion failed.";
static const field dynamic var4 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_const_ctor_error.dart:41:14: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
const var4 = C();
^";
static method main() → void {}
constants {

View file

@ -53,3 +53,13 @@ class A {
class B extends A {
const B() : super();
}
const var4 = C();
// ^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONST
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
class C {
int? x;
}

View file

@ -29,6 +29,11 @@ class A {
}
}
const var3 = fn();
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
A fn() => A();
void main() {
Expect.equals(var1.name, printString);
}