[fasta] Preserve information about const constructors in outline.

- for classes with const constructors parse field initializers;
- for const constructions parse initializer lists and default parameter
values;

Fixes issue https://github.com/dart-lang/sdk/issues/37357
Fixes issue https://github.com/dart-lang/sdk/issues/36635

Change-Id: Iff0e47f8bd2925cee9f42a2b309de4de84e99cad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108279
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Vyacheslav Egorov 2019-07-09 14:02:01 +00:00 committed by commit-bot@chromium.org
parent 25319ef7a6
commit a86db84e0a
31 changed files with 310 additions and 65 deletions

View file

@ -996,8 +996,14 @@ class AstBuilder extends StackListener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
assert(optionalOrNull('this', thisKeyword));
assert(thisKeyword == null
? periodAfterThis == null

View file

@ -762,11 +762,17 @@ class ForwardingTestListener extends ForwardingListener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
end('FormalParameter');
super.endFormalParameter(
thisKeyword, periodAfterThis, nameToken, kind, memberKind);
super.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
initializerStart, initializerEnd, kind, memberKind);
}
@override

View file

@ -297,8 +297,14 @@ class MiniAstBuilder extends StackListener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
debugEvent("FormalParameter");
pop(); // Name
pop(); // Type

View file

@ -50,4 +50,6 @@ abstract class FormalParameterBuilder<T extends TypeBuilder>
String get fullNameForErrors => name;
FormalParameterBuilder forFormalParameterInitializerScope();
void buildOutlineExpressions(LibraryBuilder library);
}

View file

@ -633,6 +633,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
ProcedureBuilder<TypeBuilder> member = this.member;
scope = member.computeFormalParameterInitializerScope(scope);
if (member is KernelConstructorBuilder) {
member.prepareInitializers();
if (member.formals != null) {
for (KernelFormalParameterBuilder formal in member.formals) {
if (formal.isInitializingFormal) {
@ -1128,6 +1129,16 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
return fakeReturn.expression;
}
void parseInitializers(Token token) {
Parser parser = new Parser(this);
if (!token.isEof) {
token = parser.parseInitializers(token);
checkEmpty(token.charOffset);
} else {
handleNoInitializers();
}
}
Expression parseFieldInitializer(Token token) {
Parser parser = new Parser(this);
token = parser.parseExpression(parser.syntheticPreviousToken(token));
@ -2886,8 +2897,14 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
debugEvent("FormalParameter");
if (thisKeyword != null) {
if (!inConstructor) {

View file

@ -59,8 +59,8 @@ class KernelBodyBuilder extends BodyBuilder {
classBuilder,
member?.isInstanceMember ?? false,
fileUri,
library.loader.typeInferenceEngine
?.createLocalTypeInferrer(fileUri, null, library));
library.loader.typeInferenceEngine?.createLocalTypeInferrer(
fileUri, classBuilder?.target?.thisType, library));
@override
void enterThenForTypePromotion(Expression condition) {

View file

@ -109,7 +109,16 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
ClassBuilder classBuilder = isClassMember ? parent : null;
KernelMetadataBuilder.buildAnnotations(
field, metadata, library, classBuilder, this);
if (constInitializerToken != null) {
// For modular compilation we need to include initializers of all const
// fields and all non-static final fields in classes with const constructors
// into the outline.
if ((isConst ||
(isFinal &&
!isStatic &&
isClassMember &&
classBuilder.hasConstConstructor)) &&
constInitializerToken != null) {
Scope scope = classBuilder?.scope ?? library.scope;
KernelBodyBuilder bodyBuilder =
new KernelBodyBuilder.forOutlineExpression(
@ -118,7 +127,6 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
isConst ? ConstantContext.inferred : ConstantContext.none;
initializer = bodyBuilder.parseFieldInitializer(constInitializerToken)
..parent = field;
constInitializerToken = null;
bodyBuilder.typeInferrer
?.inferFieldInitializer(bodyBuilder, field.type, field.initializer);
if (library.loader is SourceLoader) {
@ -128,6 +136,7 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
}
bodyBuilder.resolveRedirectingFactoryTargets();
}
constInitializerToken = null;
}
Field get target => field;

View file

@ -6,16 +6,28 @@ library fasta.kernel_formal_parameter_builder;
import 'package:kernel/ast.dart' show VariableDeclaration;
import '../constant_context.dart' show ConstantContext;
import '../modifier.dart' show finalMask, initializingFormalMask;
import '../scanner.dart' show Token;
import '../scope.dart' show Scope;
import '../source/source_loader.dart' show SourceLoader;
import 'kernel_body_builder.dart' show KernelBodyBuilder;
import 'kernel_builder.dart'
show
ClassBuilder,
Declaration,
FormalParameterBuilder,
KernelConstructorBuilder,
KernelFieldBuilder,
KernelLibraryBuilder,
KernelTypeBuilder,
LibraryBuilder,
MetadataBuilder,
TypeBuilder;
@ -25,6 +37,8 @@ class KernelFormalParameterBuilder
extends FormalParameterBuilder<KernelTypeBuilder> {
VariableDeclaration declaration;
Token initializerToken;
KernelFormalParameterBuilder(
List<MetadataBuilder> metadata,
int modifiers,
@ -83,4 +97,31 @@ class KernelFormalParameterBuilder
}
}
}
@override
void buildOutlineExpressions(LibraryBuilder library) {
// For modular compilation we need to include initializers for all
// parameters of const constructors into the outline.
if (parent is KernelConstructorBuilder &&
parent.target.isConst &&
initializerToken != null) {
final ClassBuilder classBuilder = parent.parent;
Scope scope = classBuilder.scope;
KernelBodyBuilder bodyBuilder =
new KernelBodyBuilder.forOutlineExpression(
library, classBuilder, this, scope, fileUri);
bodyBuilder.constantContext = ConstantContext.required;
target.initializer = bodyBuilder.parseFieldInitializer(initializerToken)
..parent = target;
bodyBuilder.typeInferrer?.inferParameterInitializer(
bodyBuilder, target.initializer, target.type);
if (library.loader is SourceLoader) {
SourceLoader loader = library.loader;
loader.transformPostInference(target, bodyBuilder.transformSetLiterals,
bodyBuilder.transformCollections);
}
bodyBuilder.resolveRedirectingFactoryTargets();
}
initializerToken = null;
}
}

View file

@ -704,7 +704,7 @@ class KernelLibraryBuilder
currentDeclaration?.hasConstConstructor = true;
// const constructors will have their initializers compiled and written
// into the outline.
procedure.beginInitializers = beginInitializers;
procedure.beginInitializers = beginInitializers ?? Token.eof(-1);
}
}
@ -901,12 +901,14 @@ class KernelLibraryBuilder
KernelTypeBuilder type,
String name,
bool hasThis,
int charOffset) {
int charOffset,
Token initializerToken) {
if (hasThis) {
modifiers |= initializingFormalMask;
}
KernelFormalParameterBuilder formal = new KernelFormalParameterBuilder(
metadata, modifiers, type, name, this, charOffset);
formal.initializerToken = initializerToken;
if (legacyMode && hasThis && type == null) {
(untypedInitializingFormals ??= <KernelFormalParameterBuilder>[])
.add(formal);

View file

@ -36,6 +36,8 @@ import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
import '../../scanner/token.dart' show Token;
import '../constant_context.dart' show ConstantContext;
import '../loader.dart' show Loader;
import '../messages.dart'
@ -55,9 +57,13 @@ import '../problems.dart' show unexpected;
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../source/source_loader.dart' show SourceLoader;
import '../type_inference/type_inference_engine.dart'
show IncludesTypeParametersCovariantly;
import 'kernel_body_builder.dart' show KernelBodyBuilder;
import 'kernel_builder.dart'
show
ClassBuilder,
@ -238,6 +244,22 @@ abstract class KernelFunctionBuilder
Member build(SourceLibraryBuilder library);
@override
void buildOutlineExpressions(LibraryBuilder library) {
KernelMetadataBuilder.buildAnnotations(
target, metadata, library, isClassMember ? parent : null, this);
if (formals != null) {
// For const constructors we need to include default parameter values
// into the outline. For all other formals we need to call
// buildOutlineExpressions to clear initializerToken to prevent
// consuming too much memory.
for (FormalParameterBuilder<KernelTypeBuilder> formal in formals) {
formal.buildOutlineExpressions(library);
}
}
}
void becomeNative(Loader loader) {
Declaration constructor = loader.getNativeAnnotation();
Arguments arguments =
@ -359,12 +381,6 @@ class KernelProcedureBuilder extends KernelFunctionBuilder {
return procedure;
}
@override
void buildOutlineExpressions(LibraryBuilder library) {
KernelMetadataBuilder.buildAnnotations(
target, metadata, library, isClassMember ? parent : null, this);
}
Procedure get target => origin.procedure;
@override
@ -491,8 +507,24 @@ class KernelConstructorBuilder extends KernelFunctionBuilder {
@override
void buildOutlineExpressions(LibraryBuilder library) {
KernelMetadataBuilder.buildAnnotations(
target, metadata, library, parent, this);
super.buildOutlineExpressions(library);
// For modular compilation purposes we need to include initializers
// for const constructors into the outline.
if (isConst && beginInitializers != null) {
ClassBuilder classBuilder = parent;
KernelBodyBuilder bodyBuilder =
new KernelBodyBuilder.forOutlineExpression(
library, classBuilder, this, classBuilder.scope, fileUri);
bodyBuilder.constantContext = ConstantContext.inferred;
bodyBuilder.parseInitializers(beginInitializers);
if (library.loader is SourceLoader) {
SourceLoader loader = library.loader;
loader.transformPostInference(target, bodyBuilder.transformSetLiterals,
bodyBuilder.transformCollections);
}
bodyBuilder.resolveRedirectingFactoryTargets();
}
beginInitializers = null;
}
@ -601,6 +633,21 @@ class KernelConstructorBuilder extends KernelFunctionBuilder {
reportPatchMismatch(patch);
}
}
void prepareInitializers() {
// For const constructors we parse initializers already at the outlining
// stage, there is no easy way to make body building stage skip initializer
// parsing, so we simply clear parsed initializers and rebuild them
// again.
// Note: this method clears both initializers from the target Kernel node
// and internal state associated with parsing initializers.
if (target.isConst) {
target.initializers.length = 0;
redirectingInitializer = null;
superInitializer = null;
hasMovedSuperInitializer = false;
}
}
}
class KernelRedirectingFactoryBuilder extends KernelProcedureBuilder {

View file

@ -641,10 +641,16 @@ class ForwardingListener implements Listener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
listener?.endFormalParameter(
thisKeyword, periodAfterThis, nameToken, kind, memberKind);
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
listener?.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
initializerStart, initializerEnd, kind, memberKind);
}
@override

View file

@ -294,8 +294,14 @@ class Listener implements UnescapeErrorListener {
void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
Token covariantToken, Token varFinalOrConst) {}
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
logEvent("FormalParameter");
}

View file

@ -1495,10 +1495,12 @@ class Parser {
next = token.next;
String value = next.stringValue;
Token initializerStart, initializerEnd;
if ((identical('=', value)) || (identical(':', value))) {
Token equal = next;
initializerStart = equal.next;
listener.beginFormalParameterDefaultValueExpression();
token = parseExpression(equal);
token = initializerEnd = parseExpression(equal);
next = token.next;
listener.endFormalParameterDefaultValueExpression();
// TODO(danrubel): Consider removing the last parameter from the
@ -1519,8 +1521,8 @@ class Parser {
} else {
listener.handleFormalParameterWithoutValue(next);
}
listener.endFormalParameter(
thisKeyword, periodAfterThis, nameToken, parameterKind, memberKind);
listener.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
initializerStart, initializerEnd, parameterKind, memberKind);
return token;
}

View file

@ -103,6 +103,7 @@ class OutlineBuilder extends StackListener {
final bool stringExpectedAfterNative;
bool inConstructor = false;
bool inConstructorName = false;
bool inConstConstructor = false;
int importIndex = 0;
String nativeMethodName;
@ -746,6 +747,9 @@ class OutlineBuilder extends StackListener {
} else {
modifiers ??= <Modifier>[];
modifiers.add(Const);
if (inConstructor) {
inConstConstructor = true;
}
}
}
push(varFinalOrConst?.charOffset ?? -1);
@ -838,7 +842,7 @@ class OutlineBuilder extends StackListener {
.resolveTypes(typeVariables, library);
if (name is ParserRecovery) {
nativeMethodName = null;
inConstructor = false;
inConstructor = inConstConstructor = false;
return;
}
String constructorName =
@ -897,7 +901,7 @@ class OutlineBuilder extends StackListener {
isTopLevel: false);
}
nativeMethodName = null;
inConstructor = false;
inConstructor = inConstConstructor = false;
}
@override
@ -1015,8 +1019,14 @@ class OutlineBuilder extends StackListener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
debugEvent("FormalParameter");
int charOffset = pop();
Object name = pop();
@ -1027,7 +1037,13 @@ class OutlineBuilder extends StackListener {
push(name);
} else {
push(library.addFormalParameter(
metadata, modifiers, type, name, thisKeyword != null, charOffset));
metadata,
modifiers,
type,
name,
thisKeyword != null,
charOffset,
inConstConstructor ? initializerStart : null));
}
}
@ -1520,7 +1536,7 @@ class OutlineBuilder extends StackListener {
endToken.charOffset,
nativeMethodName);
nativeMethodName = null;
inConstructor = false;
inConstructor = inConstConstructor = false;
}
@override

View file

@ -71,7 +71,7 @@ import '../fasta_codes.dart'
import '../import.dart' show Import;
import '../modifier.dart' show constMask;
import '../modifier.dart' show constMask, finalMask;
import '../problems.dart' show unexpected, unhandled;
@ -400,8 +400,11 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
int modifiers, T type, List<FieldInfo> fieldInfos) {
for (FieldInfo info in fieldInfos) {
bool isConst = modifiers & constMask != 0;
bool isFinal = modifiers & finalMask != 0;
bool potentiallyNeedInitializerInOutline = isConst || isFinal;
Token startToken;
if (isConst || (type == null && !legacyMode)) {
if (potentiallyNeedInitializerInOutline ||
(type == null && !legacyMode)) {
startToken = info.initializerToken;
}
if (startToken != null) {
@ -414,7 +417,8 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
bool hasInitializer = info.initializerToken != null;
addField(documentationComment, metadata, modifiers, type, info.name,
info.charOffset, info.charEndOffset, startToken, hasInitializer,
constInitializerToken: isConst ? startToken : null);
constInitializerToken:
potentiallyNeedInitializerInOutline ? startToken : null);
}
}
@ -486,8 +490,14 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
int charEndOffset,
String nativeMethodName);
FormalParameterBuilder addFormalParameter(List<MetadataBuilder> metadata,
int modifiers, T type, String name, bool hasThis, int charOffset);
FormalParameterBuilder addFormalParameter(
List<MetadataBuilder> metadata,
int modifiers,
T type,
String name,
bool hasThis,
int charOffset,
Token initializerToken);
TypeVariableBuilder addTypeVariable(String name, T bound, int charOffset);

View file

@ -619,8 +619,14 @@ class TypePromotionLookAheadListener extends Listener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
debugEvent("FormalParameter", thisKeyword);
state.pop(); // Parameter name.
}

View file

@ -2802,8 +2802,14 @@ class TypeInfoListener implements Listener {
}
@override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
void endFormalParameter(
Token thisKeyword,
Token periodAfterThis,
Token nameToken,
Token initializerStart,
Token initializerEnd,
FormalParameterKind kind,
MemberKind memberKind) {
calls.add('endFormalParameter $thisKeyword $periodAfterThis '
'$nameToken $kind $memberKind');
}

View file

@ -12,6 +12,7 @@ class Strength extends core::Object {
final field core::int value;
final field core::String name;
const constructor •(core::int value, core::String name) → self::Strength
: self::Strength::value = value, self::Strength::name = name
;
method nextWeaker() → self::Strength
;
@ -27,6 +28,7 @@ class Strength extends core::Object {
abstract class Constraint extends core::Object {
final field self::Strength strength;
const constructor •(self::Strength strength) → self::Constraint
: self::Constraint::strength = strength
;
abstract method isSatisfied() → core::bool;
abstract method markUnsatisfied() → void;

View file

@ -5,6 +5,7 @@ import "dart:core" as core;
class Fisk<T extends core::Object = dynamic> extends core::Object {
final field self::Fisk::T x;
const constructor fisk(self::Fisk::T x) → self::Fisk<self::Fisk::T>
: self::Fisk::x = x
;
}
class Foo extends core::Object {

View file

@ -11,10 +11,6 @@ library;
// external foo(String x) {
// ^^^^^^^^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:10:26: Error: New expression is not a constant expression.
// const A.named2() : x = new Object();
// ^^^
@ -31,6 +27,10 @@ library;
// const A.named2() : x = new Object();
// ^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:13:24: Error: An external or native method can't have a body.
// external foo(String x) {
// ^

View file

@ -11,10 +11,6 @@ library;
// external foo(String x) {
// ^^^^^^^^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:10:26: Error: New expression is not a constant expression.
// const A.named2() : x = new Object();
// ^^^
@ -31,6 +27,10 @@ library;
// const A.named2() : x = new Object();
// ^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:13:24: Error: An external or native method can't have a body.
// external foo(String x) {
// ^

View file

@ -11,14 +11,34 @@ library;
// external foo(String x) {
// ^^^^^^^^
//
// pkg/front_end/testcases/many_errors.dart:10:26: Error: New expression is not a constant expression.
// const A.named2() : x = new Object();
// ^^^
//
// pkg/front_end/testcases/many_errors.dart:10:24: Warning: 'x' is a final instance variable that has already been initialized.
// const A.named2() : x = new Object();
// ^
// pkg/front_end/testcases/many_errors.dart:6:9: Context: 'x' was initialized here.
// final x = null;
// ^
//
// pkg/front_end/testcases/many_errors.dart:10:24: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// Try using a constructor or factory that is 'const'.
// const A.named2() : x = new Object();
// ^
//
import self as self;
import "dart:core" as core;
class A extends core::Object {
final field dynamic x;
final field dynamic x = null;
constructor named1() → self::A
;
const constructor named2() → self::A
: final dynamic #t1 = throw invalid-expression "pkg/front_end/testcases/many_errors.dart:10:24: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
const A.named2() : x = new Object();
^"
;
}
class B extends core::Object {

View file

@ -11,10 +11,6 @@ library;
// external foo(String x) {
// ^^^^^^^^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:10:26: Error: New expression is not a constant expression.
// const A.named2() : x = new Object();
// ^^^
@ -31,6 +27,10 @@ library;
// const A.named2() : x = new Object();
// ^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:13:24: Error: An external or native method can't have a body.
// external foo(String x) {
// ^

View file

@ -11,10 +11,6 @@ library;
// external foo(String x) {
// ^^^^^^^^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:10:26: Error: New expression is not a constant expression.
// const A.named2() : x = new Object();
// ^^^
@ -31,6 +27,10 @@ library;
// const A.named2() : x = new Object();
// ^
//
// pkg/front_end/testcases/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
// const A.named1() sync* {}
// ^
//
// pkg/front_end/testcases/many_errors.dart:13:24: Error: An external or native method can't have a body.
// external foo(String x) {
// ^

View file

@ -5,11 +5,13 @@ import "dart:core" as core;
class A extends core::Object {
final field core::int bar;
const constructor •(core::int bar) → self::A
: self::A::bar = bar
;
}
class B extends core::Object {
final field self::A baz;
const constructor •(self::A baz) → self::B
: self::B::baz = baz
;
}
class C extends core::Object {

View file

@ -5,6 +5,7 @@ import "dart:core" as core;
class A extends core::Object {
final field core::int x;
const constructor •(core::int x) → self::A
: self::A::x = x
;
}
static method main() → dynamic

View file

@ -1,9 +1,21 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Warning: Too many positional arguments: 0 allowed, but 1 found.
// Try removing the extra positional arguments.
// const C() : this.x(1);
// ^
//
import self as self;
import "dart:core" as core;
class C extends core::Object {
const constructor •() → self::C
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
const C() : this.x(1);
^"
;
const constructor x() → self::C
;

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart:10:20: Warning: Too few positional arguments: 1 required, 0 given.
// const B() : super();
// ^
//
import self as self;
import "dart:core" as core;
@ -8,6 +15,9 @@ class A extends core::Object {
}
class B extends self::A {
const constructor •() → self::B
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart:10:20: Error: Too few positional arguments: 1 required, 0 given.
const B() : super();
^"
;
}
static method main() → dynamic

View file

@ -7,11 +7,18 @@ library;
// const C() : this.x;
// ^^^^
//
// pkg/front_end/testcases/rasta/issue_000034.dart:6:15: Error: Can't access 'this' in a field initializer.
// const C() : this.x;
// ^^^^
//
import self as self;
import "dart:core" as core;
class C extends core::Object {
const constructor •() → self::C
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000034.dart:6:15: Error: This couldn't be parsed.
const C() : this.x;
^"
;
}
static method main() → dynamic

View file

@ -11,6 +11,7 @@ class A<N extends core::Object = dynamic, S extends core::Object = dynamic, U ex
constructor empty() → self::A<self::A::N, self::A::S, self::A::U>
;
const constructor c(self::A::U u, self::A::S s) → self::A<self::A::N, self::A::S, self::A::U>
: self::A::field = const <dynamic>[null]
;
static factory f<N extends core::Object = dynamic, S extends core::Object = dynamic, U extends core::Object = dynamic>(self::A::f::S s) → self::A<self::A::f::N, self::A::f::S, self::A::f::U>
;

View file

@ -13,6 +13,7 @@ class A extends core::Object {
}
class B<T extends core::Object = dynamic> extends self::A {
const constructor •() → self::B<self::B::T>
: super self::A::empty()
;
method toString() → core::String
;