[cfe] Const factories when const functions enabled.
Change-Id: Ifd24678c0ac191c5cc6f1d60443ab96f56cbba7d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192400 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Reviewed-by: Jake Macdonald <jakemac@google.com> Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
a38a2dd343
commit
b5d4d26abe
@@ -1173,6 +1173,11 @@ class ForwardingListener implements Listener {
|
||||
listener?.handleConditionalExpressionColon();
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
listener?.handleConstFactory(constKeyword);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleContinueStatement(
|
||||
bool hasTarget, Token continueKeyword, Token endToken) {
|
||||
|
||||
@@ -1360,6 +1360,10 @@ class Listener implements UnescapeErrorListener {
|
||||
logEvent("ConstExpression");
|
||||
}
|
||||
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
logEvent("ConstFactory");
|
||||
}
|
||||
|
||||
/// Called before parsing a "for" control flow list, set, or map entry.
|
||||
/// Ended by either [endForControlFlow] or [endForInControlFlow].
|
||||
void beginForControlFlow(Token? awaitToken, Token forToken) {}
|
||||
|
||||
@@ -4063,7 +4063,7 @@ class Parser {
|
||||
} else {
|
||||
if (varFinalOrConst != null && !optional('native', next)) {
|
||||
if (optional('const', varFinalOrConst)) {
|
||||
reportRecoverableError(varFinalOrConst, codes.messageConstFactory);
|
||||
listener.handleConstFactory(varFinalOrConst);
|
||||
}
|
||||
}
|
||||
token = parseFunctionBody(
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
|
||||
messageAbstractLateField,
|
||||
messageAbstractStaticField,
|
||||
messageConstConstructorWithBody,
|
||||
messageConstFactory,
|
||||
messageConstructorWithTypeParameters,
|
||||
messageDirectiveAfterDeclaration,
|
||||
messageExpectedStatement,
|
||||
@@ -2574,6 +2575,13 @@ class AstBuilder extends StackListener {
|
||||
push(referenceOffset);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
debugEvent("ConstFactory");
|
||||
// TODO(kallentu): Removal of const factory error for const function feature
|
||||
handleRecoverableError(messageConstFactory, constKeyword, constKeyword);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleContinueStatement(
|
||||
bool hasTarget, Token continueKeyword, Token semicolon) {
|
||||
|
||||
@@ -4768,6 +4768,15 @@ class BodyBuilder extends ScopeListener<JumpTarget>
|
||||
inMetadata: false);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
debugEvent("ConstFactory");
|
||||
if (!libraryBuilder.enableConstFunctionsInLibrary) {
|
||||
handleRecoverableError(
|
||||
fasta.messageConstFactory, constKeyword, constKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void beginIfControlFlow(Token ifToken) {
|
||||
// TODO(danrubel): consider removing this when control flow support is added
|
||||
|
||||
@@ -2783,6 +2783,11 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
||||
} else {
|
||||
name = '${target.enclosingClass.name}.${name}';
|
||||
}
|
||||
|
||||
if (enableConstFunctions) {
|
||||
return _handleFunctionInvocation(
|
||||
node.target.function, typeArguments, positionals, named);
|
||||
}
|
||||
}
|
||||
return createInvalidExpressionConstant(node, "Invocation of $name");
|
||||
}
|
||||
|
||||
@@ -632,6 +632,11 @@ class DietListener extends StackListenerImpl {
|
||||
_inRedirectingFactory = true;
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
debugEvent("ConstFactory");
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
|
||||
debugEvent("NativeFunctionBody");
|
||||
|
||||
@@ -2044,6 +2044,14 @@ class OutlineBuilder extends StackListenerImpl {
|
||||
push(MethodBody.RedirectingFactoryBody);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
debugEvent("ConstFactory");
|
||||
if (!libraryBuilder.enableConstFunctionsInLibrary) {
|
||||
handleRecoverableError(messageConstFactory, constKeyword, constKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endFieldInitializer(Token assignmentOperator, Token token) {
|
||||
debugEvent("FieldInitializer");
|
||||
|
||||
@@ -1970,6 +1970,13 @@ abstract class AbstractDirectParserASTListener implements Listener {
|
||||
seen(data);
|
||||
}
|
||||
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
DirectParserASTContentConstFactoryHandle data =
|
||||
new DirectParserASTContentConstFactoryHandle(DirectParserASTType.HANDLE,
|
||||
constKeyword: constKeyword);
|
||||
seen(data);
|
||||
}
|
||||
|
||||
void beginForControlFlow(Token awaitToken, Token forToken) {
|
||||
DirectParserASTContentForControlFlowBegin data =
|
||||
new DirectParserASTContentForControlFlowBegin(DirectParserASTType.BEGIN,
|
||||
@@ -5814,6 +5821,18 @@ class DirectParserASTContentConstExpressionEnd extends DirectParserASTContent {
|
||||
};
|
||||
}
|
||||
|
||||
class DirectParserASTContentConstFactoryHandle extends DirectParserASTContent {
|
||||
final Token constKeyword;
|
||||
|
||||
DirectParserASTContentConstFactoryHandle(DirectParserASTType type,
|
||||
{this.constKeyword})
|
||||
: super("ConstFactory", type);
|
||||
|
||||
Map<String, Object> get deprecatedArguments => {
|
||||
"constKeyword": constKeyword,
|
||||
};
|
||||
}
|
||||
|
||||
class DirectParserASTContentForControlFlowBegin extends DirectParserASTContent {
|
||||
final Token awaitToken;
|
||||
final Token forToken;
|
||||
|
||||
@@ -1765,6 +1765,11 @@ class ParserTestListener implements Listener {
|
||||
doPrint('endConstExpression(' '$token)');
|
||||
}
|
||||
|
||||
void handleConstFactory(Token constKeyword) {
|
||||
seen(constKeyword);
|
||||
doPrint('handleConstFactory(' '$constKeyword)');
|
||||
}
|
||||
|
||||
void beginForControlFlow(Token? awaitToken, Token forToken) {
|
||||
seen(awaitToken);
|
||||
seen(forToken);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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 const factories with const functions.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const printConst = MessageType.parse("print");
|
||||
|
||||
class MessageType {
|
||||
static const print = MessageType._('print');
|
||||
|
||||
static const skip = MessageType._('skip');
|
||||
|
||||
final String name;
|
||||
|
||||
const factory MessageType.parse(String name) {
|
||||
if (name == 'print') {
|
||||
return MessageType.print;
|
||||
}
|
||||
return MessageType.skip;
|
||||
}
|
||||
|
||||
const MessageType._(this.name);
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(printConst, MessageType.print);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class MessageType extends core::Object /*hasConstConstructor*/ {
|
||||
static const field self::MessageType print = #C2;
|
||||
static const field self::MessageType skip = #C4;
|
||||
final field core::String name;
|
||||
const constructor _(core::String name) → self::MessageType
|
||||
: self::MessageType::name = name, super core::Object::•()
|
||||
;
|
||||
static factory parse(core::String name) → self::MessageType {
|
||||
if(name.{core::String::==}("print")) {
|
||||
return #C2;
|
||||
}
|
||||
return #C4;
|
||||
}
|
||||
}
|
||||
static const field self::MessageType printConst = #C2;
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, #C2);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = "print"
|
||||
#C2 = self::MessageType {name:#C1}
|
||||
#C3 = "skip"
|
||||
#C4 = self::MessageType {name:#C3}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_const_factory.dart:
|
||||
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class MessageType extends core::Object /*hasConstConstructor*/ {
|
||||
static const field self::MessageType print = #C2;
|
||||
static const field self::MessageType skip = #C4;
|
||||
final field core::String name;
|
||||
const constructor _(core::String name) → self::MessageType
|
||||
: self::MessageType::name = name, super core::Object::•()
|
||||
;
|
||||
static factory parse(core::String name) → self::MessageType {
|
||||
if(name.{core::String::==}("print")) {
|
||||
return #C2;
|
||||
}
|
||||
return #C4;
|
||||
}
|
||||
}
|
||||
static const field self::MessageType printConst = #C2;
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, #C2);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = "print"
|
||||
#C2 = self::MessageType {name:#C1}
|
||||
#C3 = "skip"
|
||||
#C4 = self::MessageType {name:#C3}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_const_factory.dart:
|
||||
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import "package:expect/expect.dart";
|
||||
const printConst = MessageType.parse("print");
|
||||
class MessageType {
|
||||
static const print = MessageType._('print');
|
||||
static const skip = MessageType._('skip');
|
||||
final String name;
|
||||
const factory MessageType.parse(String name) {}
|
||||
const MessageType._(this.name);
|
||||
}
|
||||
void main() {}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class MessageType {
|
||||
const MessageType._(this.name);
|
||||
const factory MessageType.parse(String name) {}
|
||||
final String name;
|
||||
static const print = MessageType._('print');
|
||||
static const skip = MessageType._('skip');
|
||||
}
|
||||
|
||||
const printConst = MessageType.parse("print");
|
||||
void main() {}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class MessageType extends core::Object /*hasConstConstructor*/ {
|
||||
static const field self::MessageType print = #C2;
|
||||
static const field self::MessageType skip = #C4;
|
||||
final field core::String name;
|
||||
const constructor _(core::String name) → self::MessageType
|
||||
: self::MessageType::name = name, super core::Object::•()
|
||||
;
|
||||
static factory parse(core::String name) → self::MessageType {
|
||||
if(name.{core::String::==}("print")) {
|
||||
return #C2;
|
||||
}
|
||||
return #C4;
|
||||
}
|
||||
}
|
||||
static const field self::MessageType printConst = #C2;
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, #C2);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = "print"
|
||||
#C2 = self::MessageType {name:#C1}
|
||||
#C3 = "skip"
|
||||
#C4 = self::MessageType {name:#C3}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_const_factory.dart:
|
||||
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class MessageType extends core::Object /*hasConstConstructor*/ {
|
||||
static const field self::MessageType print = const self::MessageType::_("print");
|
||||
static const field self::MessageType skip = const self::MessageType::_("skip");
|
||||
final field core::String name;
|
||||
const constructor _(core::String name) → self::MessageType
|
||||
: self::MessageType::name = name, super core::Object::•()
|
||||
;
|
||||
static const factory parse(core::String name) → self::MessageType
|
||||
;
|
||||
}
|
||||
static const field self::MessageType printConst = const self::MessageType::parse("print");
|
||||
static method main() → void
|
||||
;
|
||||
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_const_factory.dart:12:36 -> InstanceConstant(const MessageType{MessageType.name: "print"})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_const_factory.dart:14:35 -> InstanceConstant(const MessageType{MessageType.name: "skip"})
|
||||
Extra constant evaluation: evaluated: 4, effectively constant: 2
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
class MessageType extends core::Object /*hasConstConstructor*/ {
|
||||
static const field self::MessageType print = #C2;
|
||||
static const field self::MessageType skip = #C4;
|
||||
final field core::String name;
|
||||
const constructor _(core::String name) → self::MessageType
|
||||
: self::MessageType::name = name, super core::Object::•()
|
||||
;
|
||||
static factory parse(core::String name) → self::MessageType {
|
||||
if(name.{core::String::==}("print")) {
|
||||
return #C2;
|
||||
}
|
||||
return #C4;
|
||||
}
|
||||
}
|
||||
static const field self::MessageType printConst = #C2;
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C2, #C2);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = "print"
|
||||
#C2 = self::MessageType {name:#C1}
|
||||
#C3 = "skip"
|
||||
#C4 = self::MessageType {name:#C3}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_functions_const_factory.dart:
|
||||
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
|
||||
@@ -2,6 +2,7 @@
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE.md file.
|
||||
|
||||
const_functions/const_functions_const_factory: VerificationError
|
||||
extension_types/simple: ExpectationFileMismatchSerialized
|
||||
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized
|
||||
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized
|
||||
|
||||
@@ -20,7 +20,7 @@ regress/issue_39035.crash: EmptyOutput
|
||||
regress/issue_39091_2: EmptyOutput
|
||||
regress/utf_16_le_content.crash: EmptyOutput
|
||||
|
||||
|
||||
const_functions/const_functions_const_factory: FormatterCrash
|
||||
extensions/extension_constructor: FormatterCrash
|
||||
extensions/extension_field_with_type_parameter_usage: FormatterCrash
|
||||
extensions/issue38600: FormatterCrash
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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 const factories with const functions disabled.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const printConst = MessageType.parse("print");
|
||||
|
||||
class MessageType {
|
||||
static const print = MessageType._('print');
|
||||
|
||||
static const skip = MessageType._('skip');
|
||||
|
||||
final String name;
|
||||
|
||||
const factory MessageType.parse(String name) {
|
||||
//^^^^^
|
||||
// [analyzer] SYNTACTIC_ERROR.CONST_FACTORY
|
||||
// [cfe] Only redirecting factory constructors can be declared to be 'const'.
|
||||
if (name == 'print') {
|
||||
return MessageType.print;
|
||||
}
|
||||
return MessageType.skip;
|
||||
}
|
||||
|
||||
const MessageType._(this.name);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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 const factories with const functions.
|
||||
|
||||
// SharedOptions=--enable-experiment=const-functions
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const printConst = MessageType.parse("print");
|
||||
|
||||
class MessageType {
|
||||
static const print = MessageType._('print');
|
||||
|
||||
static const skip = MessageType._('skip');
|
||||
|
||||
final String name;
|
||||
|
||||
const factory MessageType.parse(String name) {
|
||||
//^^^^^
|
||||
// [analyzer] SYNTACTIC_ERROR.CONST_FACTORY
|
||||
if (name == 'print') {
|
||||
return MessageType.print;
|
||||
}
|
||||
return MessageType.skip;
|
||||
}
|
||||
|
||||
const MessageType._(this.name);
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(printConst, MessageType.print);
|
||||
}
|
||||
Reference in New Issue
Block a user