[cfe][PrimaryConstructors] Handle field initializers for constant primary constructors
This adds support for field initializers in constant primary constructors. Since constant constructors are included in the outline, the building of field initializers follow a different path than other field initializers. Field initializers for constant constructors moved to the constructor as part of outline computation instead as part of the general handling of constructor/field construction in the full compilation. Change-Id: I694483dce9594de708b1405de24ea63968d0c60c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/491120 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
committed by
Commit Queue
parent
0388fb800a
commit
13ecf7c8af
@@ -122,6 +122,8 @@ class RegularConstructorEncoding implements ConstructorEncoding {
|
||||
|
||||
Statement? bodyInternal;
|
||||
|
||||
List<Initializer>? _prependedInitializers;
|
||||
|
||||
RegularConstructorEncoding({
|
||||
required bool isExternal,
|
||||
required bool isEnumConstructor,
|
||||
@@ -363,12 +365,17 @@ class RegularConstructorEncoding implements ConstructorEncoding {
|
||||
// compile), and so we also clear them.
|
||||
// Note: this method clears both initializers from the target Kernel node
|
||||
// and internal state associated with parsing initializers.
|
||||
_constructor.initializers = [];
|
||||
if (_prependedInitializers != null) {
|
||||
_constructor.initializers = [..._prependedInitializers!.reversed];
|
||||
} else {
|
||||
_constructor.initializers = [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void prependInitializer(Initializer initializer) {
|
||||
initializer.parent = _constructor;
|
||||
(_prependedInitializers ??= []).add(initializer);
|
||||
_constructor.initializers.insert(0, initializer);
|
||||
}
|
||||
|
||||
@@ -477,6 +484,8 @@ mixin _ExtensionTypeConstructorEncodingMixin<T extends DeclarationBuilder>
|
||||
|
||||
Statement? bodyInternal;
|
||||
|
||||
List<Initializer>? _prependedInitializers;
|
||||
|
||||
/// If this procedure is an extension instance member or extension type
|
||||
/// instance member, [_thisVariable] holds the synthetically added `this`
|
||||
/// parameter.
|
||||
@@ -691,15 +700,17 @@ mixin _ExtensionTypeConstructorEncodingMixin<T extends DeclarationBuilder>
|
||||
// compile), and so we also clear them.
|
||||
// Note: this method clears both initializers from the target Kernel node
|
||||
// and internal state associated with parsing initializers.
|
||||
_initializers = [];
|
||||
// TODO(johnniwinther): Can these be moved here from the
|
||||
// [SourceConstructorBuilder]?
|
||||
//redirectingInitializer = null;
|
||||
//superInitializer = null;
|
||||
if (_prependedInitializers != null) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
_initializers = [..._prependedInitializers!.reversed];
|
||||
} else {
|
||||
_initializers = [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void prependInitializer(Initializer initializer) {
|
||||
(_prependedInitializers ??= []).add(initializer);
|
||||
_initializers.insert(0, initializer);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ class EnumElementDeclaration
|
||||
required DeclarationBuilder? declarationBuilder,
|
||||
required List<Annotatable> annotatables,
|
||||
required Uri annotatablesFileUri,
|
||||
required bool isClassInstanceMember,
|
||||
required bool forConstantConstructor,
|
||||
}) {
|
||||
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
|
||||
for (Annotatable annotatable in annotatables) {
|
||||
|
||||
@@ -14,8 +14,8 @@ class FieldFragment implements Fragment {
|
||||
|
||||
final int endOffset;
|
||||
|
||||
Token? _initializerToken;
|
||||
Token? _constInitializerToken;
|
||||
Token? _initializerTokenForTopLevelInference;
|
||||
Token? _initializerTokenForOutline;
|
||||
|
||||
final List<MetadataBuilder>? metadata;
|
||||
|
||||
@@ -45,7 +45,6 @@ class FieldFragment implements Fragment {
|
||||
required this.nameOffset,
|
||||
required this.endOffset,
|
||||
required Token? initializerToken,
|
||||
required Token? constInitializerToken,
|
||||
required this.metadata,
|
||||
required this.type,
|
||||
required this.isTopLevel,
|
||||
@@ -53,8 +52,8 @@ class FieldFragment implements Fragment {
|
||||
required this.enclosingScope,
|
||||
required this.enclosingDeclaration,
|
||||
required this.enclosingCompilationUnit,
|
||||
}) : _initializerToken = initializerToken,
|
||||
_constInitializerToken = constInitializerToken;
|
||||
}) : _initializerTokenForTopLevelInference = initializerToken,
|
||||
_initializerTokenForOutline = initializerToken;
|
||||
|
||||
@override
|
||||
SourcePropertyBuilder get builder {
|
||||
@@ -73,10 +72,10 @@ class FieldFragment implements Fragment {
|
||||
///
|
||||
/// This can only be called once and will hand over the responsibility of
|
||||
/// the token to the caller.
|
||||
Token? takeConstInitializerToken() {
|
||||
Token? result = _constInitializerToken;
|
||||
Token? takeInitializerTokenForOutline() {
|
||||
Token? result = _initializerTokenForOutline;
|
||||
// Ensure that we don't hold onto the token.
|
||||
_constInitializerToken = null;
|
||||
_initializerTokenForOutline = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -114,10 +113,10 @@ class FieldFragment implements Fragment {
|
||||
///
|
||||
/// This can only be called once and will hand over the responsibility of
|
||||
/// the token to the caller.
|
||||
Token? takeInitializerToken() {
|
||||
Token? result = _initializerToken;
|
||||
Token? takeInitializerTokenForTopLevelInference() {
|
||||
Token? result = _initializerTokenForTopLevelInference;
|
||||
// Ensure that we don't hold on to the token.
|
||||
_initializerToken = null;
|
||||
_initializerTokenForTopLevelInference = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,17 @@ class FieldFragmentBodyBuilderContext extends BodyBuilderContext {
|
||||
isDeclarationInstanceMember: _builder.isDeclarationInstanceMember,
|
||||
);
|
||||
|
||||
@override
|
||||
bool get inPrimaryConstructorFieldInitializer {
|
||||
DeclarationBuilder? declarationBuilder = _builder.declarationBuilder;
|
||||
if (declarationBuilder is SourceClassBuilder &&
|
||||
!_declaration.isStatic &&
|
||||
!isLateField) {
|
||||
return declarationBuilder.hasPrimaryConstructor;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
List<FormalParameterBuilder>?
|
||||
get primaryConstructorInitializerScopeParameters {
|
||||
|
||||
@@ -67,7 +67,7 @@ abstract class FieldDeclaration {
|
||||
required DeclarationBuilder? declarationBuilder,
|
||||
required List<Annotatable> annotatables,
|
||||
required Uri annotatablesFileUri,
|
||||
required bool isClassInstanceMember,
|
||||
required bool forConstantConstructor,
|
||||
});
|
||||
|
||||
int computeFieldDefaultTypes(ComputeDefaultTypeContext context);
|
||||
@@ -334,7 +334,7 @@ class RegularFieldDeclaration
|
||||
required DeclarationBuilder? declarationBuilder,
|
||||
required List<Annotatable> annotatables,
|
||||
required Uri annotatablesFileUri,
|
||||
required bool isClassInstanceMember,
|
||||
required bool forConstantConstructor,
|
||||
}) {
|
||||
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
|
||||
for (Annotatable annotatable in annotatables) {
|
||||
@@ -352,13 +352,9 @@ class RegularFieldDeclaration
|
||||
// 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.
|
||||
Token? token = _fragment.takeConstInitializerToken();
|
||||
Token? token = _fragment.takeInitializerTokenForOutline();
|
||||
if (!hasBodyBeenBuilt && token != null) {
|
||||
if ((_fragment.modifiers.isConst ||
|
||||
(isFinal &&
|
||||
isClassInstanceMember &&
|
||||
(declarationBuilder as SourceClassBuilder)
|
||||
.declaresConstConstructor))) {
|
||||
if (_fragment.modifiers.isConst || forConstantConstructor) {
|
||||
if (hasInitializerBeenComputed) {
|
||||
buildBody(classHierarchy.coreTypes, cachedFieldInitializer);
|
||||
} else {
|
||||
@@ -587,7 +583,7 @@ class RegularFieldDeclaration
|
||||
}
|
||||
|
||||
type.registerInferredTypeListener(this);
|
||||
Token? token = _fragment.takeInitializerToken();
|
||||
Token? token = _fragment.takeInitializerTokenForTopLevelInference();
|
||||
if (type is InferableTypeBuilder) {
|
||||
if (!_fragment.modifiers.hasInitializer && isStatic) {
|
||||
// A static field without type and initializer will always be inferred
|
||||
|
||||
@@ -122,7 +122,7 @@ class PrimaryConstructorFieldDeclaration
|
||||
required DeclarationBuilder? declarationBuilder,
|
||||
required List<Annotatable> annotatables,
|
||||
required Uri annotatablesFileUri,
|
||||
required bool isClassInstanceMember,
|
||||
required bool forConstantConstructor,
|
||||
}) {
|
||||
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
|
||||
for (Annotatable annotatable in annotatables) {
|
||||
|
||||
@@ -1252,7 +1252,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
return _initializers;
|
||||
}
|
||||
|
||||
Expression parseFieldInitializer(Token token) {
|
||||
Expression _parseInitializer(Token token) {
|
||||
Parser parser = new Parser(
|
||||
this,
|
||||
useImplicitCreationExpression: useImplicitCreationExpressionInCfe,
|
||||
@@ -1266,7 +1266,6 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
unionOfKinds([ValueKinds.Expression, ValueKinds.Generator]),
|
||||
]),
|
||||
);
|
||||
//print(constantContext);
|
||||
Expression expression = popForValue();
|
||||
checkEmpty(endToken.charOffset);
|
||||
return expression;
|
||||
@@ -2671,6 +2670,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
if (mustBeConst &&
|
||||
!getable.isConst &&
|
||||
!(_context.isConstructor && inFieldInitializer) &&
|
||||
!_context.inPrimaryConstructorFieldInitializer &&
|
||||
!libraryFeatures.constFunctions.isEnabled) {
|
||||
return new IncompleteErrorGenerator(
|
||||
this,
|
||||
@@ -3432,12 +3432,13 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
push(variableInitialization);
|
||||
}
|
||||
|
||||
@override
|
||||
void beginFieldInitializer(Token token) {
|
||||
inFieldInitializer = true;
|
||||
constantContext = _context.constantContext;
|
||||
inLateFieldInitializer = _context.isLateField;
|
||||
if (_context.isDeclarationInstanceContext && !inLateFieldInitializer) {
|
||||
/// Sets up the local scope for a field initializer.
|
||||
///
|
||||
/// For non-late instance fields the scope includes primary constructor
|
||||
/// parameter.
|
||||
void _enterFieldInitializerScope() {
|
||||
if (_context.inPrimaryConstructorFieldInitializer) {
|
||||
inConstructorInitializer = true;
|
||||
LocalScope enclosingScope = _localScope;
|
||||
List<FormalParameterBuilder>? parameters =
|
||||
_context.primaryConstructorInitializerScopeParameters;
|
||||
@@ -3457,6 +3458,22 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
_localScopes.push(enclosingScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pop the locals scope set up in [_enterFieldInitializerScope].
|
||||
void _exitFieldInitializerScope() {
|
||||
if (_context.inPrimaryConstructorFieldInitializer) {
|
||||
_localScopes.pop();
|
||||
inConstructorInitializer = false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void beginFieldInitializer(Token token) {
|
||||
inFieldInitializer = true;
|
||||
constantContext = _context.constantContext;
|
||||
inLateFieldInitializer = _context.isLateField;
|
||||
_enterFieldInitializerScope();
|
||||
if (_context.isAbstractField) {
|
||||
addProblem(diag.abstractFieldInitializer, token.charOffset, noLength);
|
||||
} else if (_context.isExternalField) {
|
||||
@@ -3467,13 +3484,11 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
@override
|
||||
void endFieldInitializer(Token assignmentOperator, Token endToken) {
|
||||
debugEvent("FieldInitializer");
|
||||
if (_context.isDeclarationInstanceContext && !inLateFieldInitializer) {
|
||||
_localScopes.pop();
|
||||
}
|
||||
inFieldInitializer = false;
|
||||
inLateFieldInitializer = false;
|
||||
assert(assignmentOperator.stringValue == "=");
|
||||
push(popForValue());
|
||||
_exitFieldInitializerScope();
|
||||
constantContext = ConstantContext.none;
|
||||
}
|
||||
|
||||
@@ -11188,7 +11203,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
BuildParameterInitializerResult buildParameterInitializer({
|
||||
required Token initializerToken,
|
||||
}) {
|
||||
Expression initializer = parseFieldInitializer(initializerToken);
|
||||
Expression initializer = _parseInitializer(initializerToken);
|
||||
return new BuildParameterInitializerResult(
|
||||
initializer,
|
||||
_takePendingAnnotations(),
|
||||
@@ -11448,7 +11463,9 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
}) {
|
||||
inFieldInitializer = true;
|
||||
inLateFieldInitializer = isLate;
|
||||
Expression initializer = parseFieldInitializer(startToken);
|
||||
_enterFieldInitializerScope();
|
||||
Expression initializer = _parseInitializer(startToken);
|
||||
_exitFieldInitializerScope();
|
||||
return new BuildFieldInitializerResult(
|
||||
initializer,
|
||||
_takePendingAnnotations(),
|
||||
|
||||
@@ -327,6 +327,14 @@ abstract class BodyBuilderContext {
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns `true` if the member being built is a non-late instance field
|
||||
/// in a declaration with a primary constructor.
|
||||
///
|
||||
/// Field initializers in this context have access to primary constructor
|
||||
/// parameters and should be built as if they occur in a constructor
|
||||
/// initializer.
|
||||
bool get inPrimaryConstructorFieldInitializer => false;
|
||||
|
||||
/// Returns the primary constructor parameters available in the initializer
|
||||
/// scope for instance field initializers.
|
||||
///
|
||||
|
||||
@@ -1669,7 +1669,7 @@ class KernelTarget {
|
||||
],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
} else if (!constructor.isConst) {
|
||||
constructor.prependInitializer(
|
||||
field.takePrimaryConstructorFieldInitializer(),
|
||||
);
|
||||
|
||||
@@ -262,6 +262,8 @@ class Resolver {
|
||||
fileUri: fileUri,
|
||||
);
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
List<FormalParameterBuilder>? primaryConstructorInitializerScopeParameters =
|
||||
bodyBuilderContext.primaryConstructorInitializerScopeParameters;
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
bodyBuilderContext: bodyBuilderContext,
|
||||
@@ -277,6 +279,12 @@ class Resolver {
|
||||
startToken: startToken,
|
||||
isLate: isLate,
|
||||
);
|
||||
_declareFormals(
|
||||
typeInferrer: context.typeInferrer,
|
||||
bodyBuilderContext: bodyBuilderContext,
|
||||
thisVariable: null,
|
||||
formals: primaryConstructorInitializerScopeParameters,
|
||||
);
|
||||
ExpressionInferenceResult expressionInferenceResult = context.typeInferrer
|
||||
.inferFieldInitializer(
|
||||
fileUri: fileUri,
|
||||
|
||||
@@ -671,7 +671,6 @@ class BuilderFactory {
|
||||
name: fragment.name,
|
||||
typeParameters: typeParameters,
|
||||
underscoreEnumTypeBuilder: _loader.target.underscoreEnumType,
|
||||
interfaceBuilders: fragment.interfaces,
|
||||
enumElements: fragment.enumElements,
|
||||
libraryBuilder: _enclosingLibraryBuilder,
|
||||
fileUri: fragment.fileUri,
|
||||
@@ -685,6 +684,7 @@ class BuilderFactory {
|
||||
fragment,
|
||||
_loader.target.underscoreEnumType,
|
||||
),
|
||||
modifiers: fragment.modifiers,
|
||||
);
|
||||
fragment.builder = enumBuilder;
|
||||
fragment.bodyScope.declarationBuilder = enumBuilder;
|
||||
|
||||
@@ -1089,9 +1089,15 @@ class FragmentFactoryImpl implements FragmentFactory {
|
||||
}) {
|
||||
EnumFragment declarationFragment = endEnumDeclaration();
|
||||
|
||||
Modifiers modifiers = Modifiers.empty;
|
||||
if (declarationFragment.declaresConstConstructor) {
|
||||
modifiers |= Modifiers.DeclaresConstConstructor;
|
||||
}
|
||||
|
||||
declarationFragment.compilationUnitScope = _compilationUnitScope;
|
||||
declarationFragment.metadata = metadata;
|
||||
declarationFragment.mixins = mixins;
|
||||
declarationFragment.modifiers = modifiers;
|
||||
declarationFragment.interfaces = interfaces;
|
||||
declarationFragment.startOffset = startOffset;
|
||||
declarationFragment.endOffset = endOffset;
|
||||
@@ -2137,13 +2143,7 @@ class FragmentFactoryImpl implements FragmentFactory {
|
||||
List<FieldInfo> fieldInfos,
|
||||
) {
|
||||
for (FieldInfo info in fieldInfos) {
|
||||
bool isConst = modifiers.isConst;
|
||||
bool isFinal = modifiers.isFinal;
|
||||
bool potentiallyNeedInitializerInOutline = isConst || isFinal;
|
||||
Token? startToken;
|
||||
if (potentiallyNeedInitializerInOutline || type == null) {
|
||||
startToken = info.initializerToken;
|
||||
}
|
||||
Token? startToken = info.initializerToken;
|
||||
if (startToken != null) {
|
||||
// Extract only the tokens for the initializer expression from the
|
||||
// token stream.
|
||||
@@ -2151,7 +2151,6 @@ class FragmentFactoryImpl implements FragmentFactory {
|
||||
endToken.setNext(new Token.eof(endToken.next!.offset));
|
||||
new Token.eof(startToken.previous!.offset).setNext(startToken);
|
||||
}
|
||||
bool hasInitializer = info.initializerToken != null;
|
||||
offsetMap.registerField(
|
||||
info.identifier,
|
||||
_addField(
|
||||
@@ -2163,10 +2162,6 @@ class FragmentFactoryImpl implements FragmentFactory {
|
||||
nameOffset: info.identifier.nameOffset,
|
||||
endOffset: info.endOffset,
|
||||
initializerToken: startToken,
|
||||
hasInitializer: hasInitializer,
|
||||
constInitializerToken: potentiallyNeedInitializerInOutline
|
||||
? startToken
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -2181,12 +2176,10 @@ class FragmentFactoryImpl implements FragmentFactory {
|
||||
required int nameOffset,
|
||||
required int endOffset,
|
||||
required Token? initializerToken,
|
||||
required bool hasInitializer,
|
||||
Token? constInitializerToken,
|
||||
}) {
|
||||
DeclarationFragmentImpl? enclosingDeclaration =
|
||||
_declarationFragments.currentOrNull;
|
||||
if (hasInitializer) {
|
||||
if (initializerToken != null) {
|
||||
modifiers |= Modifiers.HasInitializer;
|
||||
}
|
||||
FieldFragment fragment = new FieldFragment(
|
||||
@@ -2195,7 +2188,6 @@ class FragmentFactoryImpl implements FragmentFactory {
|
||||
nameOffset: nameOffset,
|
||||
endOffset: endOffset,
|
||||
initializerToken: initializerToken,
|
||||
constInitializerToken: constInitializerToken,
|
||||
metadata: metadata,
|
||||
type: type,
|
||||
isTopLevel: isTopLevel,
|
||||
|
||||
@@ -167,7 +167,11 @@ class SourceClassBuilder extends ClassBuilderImpl
|
||||
indexedClass,
|
||||
isAugmentation: modifiers.isAugment,
|
||||
) {
|
||||
cls.hasConstConstructor = declaresConstConstructor;
|
||||
if (!isEnum) {
|
||||
// TODO(johnniwinther): Should enums be marked as having constant
|
||||
// constructors?
|
||||
cls.hasConstConstructor = declaresConstConstructor;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -194,6 +198,17 @@ class SourceClassBuilder extends ClassBuilderImpl
|
||||
includeDuplicates: includeDuplicates,
|
||||
);
|
||||
|
||||
/// Returns `true` if this class has a primary constructor.
|
||||
bool get hasPrimaryConstructor {
|
||||
for (SourceMemberBuilder constructorBuilder in _constructorBuilders) {
|
||||
if (constructorBuilder is SourceConstructorBuilder &&
|
||||
constructorBuilder.isPrimaryConstructor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// If the class has a primary constructor, returns the parameters
|
||||
/// available in the initializer scope. Otherwise return `null`.
|
||||
List<FormalParameterBuilder>?
|
||||
@@ -638,6 +653,14 @@ class SourceClassBuilder extends ClassBuilderImpl
|
||||
filteredMembersIterator<SourceMemberBuilder>(
|
||||
includeDuplicates: false,
|
||||
).forEach(build);
|
||||
|
||||
for (SourceMemberBuilder memberBuilder in _constructorBuilders) {
|
||||
if (memberBuilder is SourceConstructorBuilder &&
|
||||
memberBuilder.isPrimaryConstructor &&
|
||||
memberBuilder.isConst) {
|
||||
memberBuilder.buildPrimaryConstructorFieldInitializers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up the constructor by [name] on the class built by this class
|
||||
|
||||
@@ -21,6 +21,7 @@ import '../builder/function_signature.dart';
|
||||
import '../builder/member_builder.dart';
|
||||
import '../builder/metadata_builder.dart';
|
||||
import '../builder/omitted_type_builder.dart';
|
||||
import '../builder/property_builder.dart';
|
||||
import '../fragment/constructor/declaration.dart';
|
||||
import '../kernel/hierarchy/class_member.dart' show ClassMember;
|
||||
import '../kernel/kernel_helper.dart' show DelayedDefaultValueCloner;
|
||||
@@ -145,6 +146,32 @@ class SourceConstructorBuilder extends SourceMemberBuilderImpl
|
||||
return null;
|
||||
}
|
||||
|
||||
void buildPrimaryConstructorFieldInitializers() {
|
||||
List<SourcePropertyBuilder> nonLateClassInstanceFieldsWithInitializers = [];
|
||||
|
||||
Iterator<SourcePropertyBuilder> fieldIterator = declarationBuilder
|
||||
.filteredMembersIterator(includeDuplicates: false);
|
||||
while (fieldIterator.moveNext()) {
|
||||
SourcePropertyBuilder fieldBuilder = fieldIterator.current;
|
||||
if (fieldBuilder.hasConcreteField &&
|
||||
declarationBuilder is SourceClassBuilder &&
|
||||
fieldBuilder.isDeclarationInstanceMember &&
|
||||
!fieldBuilder.isLate &&
|
||||
fieldBuilder.hasInitializer) {
|
||||
nonLateClassInstanceFieldsWithInitializers.add(fieldBuilder);
|
||||
}
|
||||
}
|
||||
// We prepend the initializers in reversed order to preserve normal
|
||||
// field initializer evaluation order.
|
||||
for (SourcePropertyBuilder field
|
||||
in nonLateClassInstanceFieldsWithInitializers.reversed) {
|
||||
FieldInitialization? fieldInitialization = _initializedFields?[field];
|
||||
if (fieldInitialization == null) {
|
||||
prependInitializer(field.takePrimaryConstructorFieldInitializer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Add annotations to tear-offs.
|
||||
Iterable<Annotatable> get annotatables => [invokeTarget];
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class SourceEnumBuilder extends SourceClassBuilder {
|
||||
|
||||
late final _EnumValuesFieldDeclaration _enumValuesFieldDeclaration;
|
||||
|
||||
SourceEnumBuilder.internal({
|
||||
SourceEnumBuilder({
|
||||
required String name,
|
||||
required List<SourceNominalParameterBuilder>? typeParameters,
|
||||
required TypeBuilder underscoreEnumTypeBuilder,
|
||||
@@ -92,11 +92,12 @@ class SourceEnumBuilder extends SourceClassBuilder {
|
||||
required this.endOffset,
|
||||
required IndexedClass? indexedClass,
|
||||
required ClassDeclaration classDeclaration,
|
||||
required Modifiers modifiers,
|
||||
}) : _underscoreEnumTypeBuilder = underscoreEnumTypeBuilder,
|
||||
_introductory = classDeclaration,
|
||||
_enumElements = enumElements,
|
||||
super(
|
||||
modifiers: Modifiers.empty,
|
||||
modifiers: modifiers,
|
||||
name: name,
|
||||
typeParameters: typeParameters,
|
||||
typeParameterScope: typeParameterScope,
|
||||
@@ -108,40 +109,6 @@ class SourceEnumBuilder extends SourceClassBuilder {
|
||||
introductory: classDeclaration,
|
||||
);
|
||||
|
||||
factory SourceEnumBuilder({
|
||||
required String name,
|
||||
required List<SourceNominalParameterBuilder>? typeParameters,
|
||||
required TypeBuilder underscoreEnumTypeBuilder,
|
||||
required List<TypeBuilder>? interfaceBuilders,
|
||||
required List<EnumElementFragment> enumElements,
|
||||
required SourceLibraryBuilder libraryBuilder,
|
||||
required Uri fileUri,
|
||||
required int startOffset,
|
||||
required int nameOffset,
|
||||
required int endOffset,
|
||||
required IndexedClass? indexedClass,
|
||||
required LookupScope typeParameterScope,
|
||||
required DeclarationNameSpaceBuilder nameSpaceBuilder,
|
||||
required ClassDeclaration classDeclaration,
|
||||
}) {
|
||||
SourceEnumBuilder enumBuilder = new SourceEnumBuilder.internal(
|
||||
name: name,
|
||||
typeParameters: typeParameters,
|
||||
underscoreEnumTypeBuilder: underscoreEnumTypeBuilder,
|
||||
typeParameterScope: typeParameterScope,
|
||||
nameSpaceBuilder: nameSpaceBuilder,
|
||||
enumElements: enumElements,
|
||||
libraryBuilder: libraryBuilder,
|
||||
fileUri: fileUri,
|
||||
startOffset: startOffset,
|
||||
nameOffset: nameOffset,
|
||||
endOffset: endOffset,
|
||||
indexedClass: indexedClass,
|
||||
classDeclaration: classDeclaration,
|
||||
);
|
||||
return enumBuilder;
|
||||
}
|
||||
|
||||
@override
|
||||
void buildScopes(LibraryBuilder coreLibrary) {
|
||||
_createTypeBuilders(coreLibrary);
|
||||
@@ -732,7 +699,7 @@ class _EnumValuesFieldDeclaration
|
||||
required DeclarationBuilder? declarationBuilder,
|
||||
required List<Annotatable> annotatables,
|
||||
required Uri annotatablesFileUri,
|
||||
required bool isClassInstanceMember,
|
||||
required bool forConstantConstructor,
|
||||
}) {
|
||||
List<Expression> values = <Expression>[];
|
||||
for (EnumElementFragment enumElement in _sourceEnumBuilder._enumElements) {
|
||||
|
||||
@@ -192,6 +192,7 @@ class SourcePropertyBuilder extends SourceMemberBuilderImpl
|
||||
ClassHierarchy classHierarchy,
|
||||
List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
|
||||
) {
|
||||
DeclarationBuilder? declarationBuilder = this.declarationBuilder;
|
||||
if (!hasBuiltOutlineExpressions) {
|
||||
_introductoryField?.buildFieldOutlineExpressions(
|
||||
classHierarchy: classHierarchy,
|
||||
@@ -203,7 +204,10 @@ class SourcePropertyBuilder extends SourceMemberBuilderImpl
|
||||
writeTarget as Annotatable,
|
||||
],
|
||||
annotatablesFileUri: readTarget!.fileUri,
|
||||
isClassInstanceMember: isClassInstanceMember,
|
||||
forConstantConstructor:
|
||||
declarationBuilder is SourceClassBuilder &&
|
||||
!isStatic &&
|
||||
declarationBuilder.declaresConstConstructor,
|
||||
);
|
||||
_introductoryGetable?.buildGetterOutlineExpressions(
|
||||
classHierarchy: classHierarchy,
|
||||
|
||||
@@ -6,7 +6,7 @@ class E extends core::_Enum /*isEnum*/ {
|
||||
enum-element static const field self::E one = const self::E::•(0, "one", 1);
|
||||
enum-element static const field self::E two = const self::E::•(1, "two", 2);
|
||||
final field core::int foo;
|
||||
final field core::int bar;
|
||||
final field core::int bar = 42;
|
||||
static field self::E staticFoo;
|
||||
static const field core::List<self::E> values = const <self::E>[self::E::one, self::E::two];
|
||||
const constructor •(core::int #index, core::String #name, core::int foo) → self::E
|
||||
@@ -25,7 +25,7 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
|
||||
enum-element static const field self::E2<core::num> one = const self::E2::•<core::num>(0, "one", 1);
|
||||
enum-element static const field self::E2<core::String> two = const self::E2::•<core::String>(1, "two", "2");
|
||||
final field self::E2::X% foo;
|
||||
final field self::E2::X? bar;
|
||||
final field self::E2::X? bar = null;
|
||||
static field () → self::E2<dynamic> staticFoo;
|
||||
static const field core::List<self::E2<dynamic>> values = const <self::E2<dynamic>>[self::E2::one, self::E2::two];
|
||||
const constructor •(core::int #index, core::String #name, self::E2::X% foo) → self::E2<self::E2::X%>
|
||||
@@ -45,9 +45,9 @@ static method main() → dynamic
|
||||
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:6:3 -> InstanceConstant(const E{E.foo: 1, E.bar: null, _Enum.index: 0, _Enum._name: "one"})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:7:3 -> InstanceConstant(const E{E.foo: 2, E.bar: null, _Enum.index: 1, _Enum._name: "two"})
|
||||
Evaluated: ListLiteral @ org-dartlang-testcase:///members.dart:5:6 -> ListConstant(const <E>[const E{E.foo: 1, E.bar: null, _Enum.index: 0, _Enum._name: "one"}, const E{E.foo: 2, E.bar: null, _Enum.index: 1, _Enum._name: "two"}])
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:6:3 -> InstanceConstant(const E{E.foo: 1, E.bar: 42, _Enum.index: 0, _Enum._name: "one"})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:7:3 -> InstanceConstant(const E{E.foo: 2, E.bar: 42, _Enum.index: 1, _Enum._name: "two"})
|
||||
Evaluated: ListLiteral @ org-dartlang-testcase:///members.dart:5:6 -> ListConstant(const <E>[const E{E.foo: 1, E.bar: 42, _Enum.index: 0, _Enum._name: "one"}, const E{E.foo: 2, E.bar: 42, _Enum.index: 1, _Enum._name: "two"}])
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:24:3 -> InstanceConstant(const E2<num>{E2.foo: 1, E2.bar: null, _Enum.index: 0, _Enum._name: "one"})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:25:3 -> InstanceConstant(const E2<String>{E2.foo: "2", E2.bar: null, _Enum.index: 1, _Enum._name: "two"})
|
||||
Evaluated: ListLiteral @ org-dartlang-testcase:///members.dart:23:6 -> ListConstant(const <E2<dynamic>>[const E2<num>{E2.foo: 1, E2.bar: null, _Enum.index: 0, _Enum._name: "one"}, const E2<String>{E2.foo: "2", E2.bar: null, _Enum.index: 1, _Enum._name: "two"}])
|
||||
|
||||
@@ -16,7 +16,7 @@ import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class Foo extends core::Object /*hasConstConstructor*/ {
|
||||
field self::Foo x;
|
||||
field self::Foo x = const self::Foo::•();
|
||||
const constructor •({core::bool x = true}) → self::Foo
|
||||
: super core::Object::•()
|
||||
;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2026, 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.
|
||||
|
||||
class C0 {
|
||||
final int a;
|
||||
final int b;
|
||||
const new(int c, dynamic d) : a = d.length, b = c;
|
||||
}
|
||||
|
||||
class const C1(int c, dynamic d) {
|
||||
final int a = d.length;
|
||||
final int b = c;
|
||||
}
|
||||
|
||||
class const C2(int c, dynamic d) {
|
||||
final int a;
|
||||
final int b;
|
||||
|
||||
this : a = d.length, b = c;
|
||||
}
|
||||
|
||||
class const C3(int c, dynamic d) {
|
||||
final int a = d.length;
|
||||
final int b;
|
||||
|
||||
this : b = c;
|
||||
}
|
||||
|
||||
class const C4(int c, dynamic d) {
|
||||
final int a = d.length;
|
||||
final int b = c;
|
||||
|
||||
this : a = d.length, b = c;
|
||||
}
|
||||
|
||||
class const C5(int c, dynamic d) {
|
||||
int a = d.length;
|
||||
int b = c;
|
||||
int? _;
|
||||
}
|
||||
|
||||
class const C6(int c, dynamic d) {
|
||||
var a = d.length;
|
||||
var b = c;
|
||||
var _;
|
||||
}
|
||||
|
||||
main() {
|
||||
const a = C0(0, '1234');
|
||||
expect(4, a.a);
|
||||
expect(0, a.b);
|
||||
|
||||
const b = C1(1, '12345');
|
||||
expect(5, b.a);
|
||||
expect(1, b.b);
|
||||
|
||||
const c = C2(2, '123456');
|
||||
expect(6, c.a);
|
||||
expect(2, c.b);
|
||||
|
||||
const d = C3(3, '1234567');
|
||||
expect(7, d.a);
|
||||
expect(3, d.b);
|
||||
}
|
||||
|
||||
test() {
|
||||
const e = C4(0, '');
|
||||
const f = C5(0, '');
|
||||
const g = C6(0, '');
|
||||
}
|
||||
|
||||
expect(expected, actual) {
|
||||
if (expected != actual) throw 'Expected $expected, actual $actual';
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
// this : a = d.length, b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:31:13: Context: 'a' was initialized here.
|
||||
// final int a = d.length;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:24: Error: 'b' is a final instance variable that was initialized at the declaration.
|
||||
// this : a = d.length, b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:32:13: Context: 'b' was initialized here.
|
||||
// final int b = c;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:37:15: Error: Constructor is marked 'const' so all fields must be final.
|
||||
// class const C5(int c, dynamic d) {
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:38:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// int a = d.length;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:39:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// int b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:40:8: Context: Field isn't final, but constructor is 'const'.
|
||||
// int? _;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:43:15: Error: Constructor is marked 'const' so all fields must be final.
|
||||
// class const C6(int c, dynamic d) {
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:44:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var a = d.length;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:45:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:46:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var _;
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class C0 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(core::int c, dynamic d) → self::C0
|
||||
: self::C0::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C0::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C1 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C1
|
||||
: self::C1::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C1::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C2 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C2
|
||||
: self::C2::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C2::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C3 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C3
|
||||
: self::C3::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C3::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C4 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C4
|
||||
: self::C4::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C4::b = c, invalid-initializer "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^", invalid-initializer "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:24: Error: 'b' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^"
|
||||
;
|
||||
}
|
||||
class C5 extends core::Object /*hasConstConstructor*/ {
|
||||
field core::int a;
|
||||
field core::int b;
|
||||
field core::int? _ = null;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C5
|
||||
: self::C5::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C5::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C6 extends core::Object /*hasConstConstructor*/ {
|
||||
field dynamic a;
|
||||
field core::int b;
|
||||
field dynamic _ = null;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C6
|
||||
: self::C6::a = d{dynamic}.length, self::C6::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
const self::C0 a = #C3;
|
||||
self::expect(4, #C3.{self::C0::a}{core::int});
|
||||
self::expect(0, #C3.{self::C0::b}{core::int});
|
||||
const self::C1 b = #C6;
|
||||
self::expect(5, #C6.{self::C1::a}{core::int});
|
||||
self::expect(1, #C6.{self::C1::b}{core::int});
|
||||
const self::C2 c = #C9;
|
||||
self::expect(6, #C9.{self::C2::a}{core::int});
|
||||
self::expect(2, #C9.{self::C2::b}{core::int});
|
||||
const self::C3 d = #C12;
|
||||
self::expect(7, #C12.{self::C3::a}{core::int});
|
||||
self::expect(3, #C12.{self::C3::b}{core::int});
|
||||
}
|
||||
static method test() → dynamic {
|
||||
const self::C4 e = invalid-expression "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^";
|
||||
const self::C5 f = #C14;
|
||||
const self::C6 g = #C15;
|
||||
}
|
||||
static method expect(dynamic expected, dynamic actual) → dynamic {
|
||||
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
|
||||
throw "Expected ${expected}, actual ${actual}";
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 4
|
||||
#C2 = 0
|
||||
#C3 = self::C0 {a:#C1, b:#C2}
|
||||
#C4 = 5
|
||||
#C5 = 1
|
||||
#C6 = self::C1 {a:#C4, b:#C5}
|
||||
#C7 = 6
|
||||
#C8 = 2
|
||||
#C9 = self::C2 {a:#C7, b:#C8}
|
||||
#C10 = 7
|
||||
#C11 = 3
|
||||
#C12 = self::C3 {a:#C10, b:#C11}
|
||||
#C13 = null
|
||||
#C14 = self::C5 {a:#C2, b:#C2, _:#C13}
|
||||
#C15 = self::C6 {a:#C2, b:#C2, _:#C13}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_parameters.dart:
|
||||
- C0. (from org-dartlang-testcase:///const_parameters.dart:8:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
|
||||
- C1. (from org-dartlang-testcase:///const_parameters.dart:11:15)
|
||||
- C2. (from org-dartlang-testcase:///const_parameters.dart:16:15)
|
||||
- C3. (from org-dartlang-testcase:///const_parameters.dart:23:15)
|
||||
- C4. (from org-dartlang-testcase:///const_parameters.dart:30:15)
|
||||
- C5. (from org-dartlang-testcase:///const_parameters.dart:37:15)
|
||||
- C6. (from org-dartlang-testcase:///const_parameters.dart:43:15)
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
// this : a = d.length, b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:31:13: Context: 'a' was initialized here.
|
||||
// final int a = d.length;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:24: Error: 'b' is a final instance variable that was initialized at the declaration.
|
||||
// this : a = d.length, b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:32:13: Context: 'b' was initialized here.
|
||||
// final int b = c;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:37:15: Error: Constructor is marked 'const' so all fields must be final.
|
||||
// class const C5(int c, dynamic d) {
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:38:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// int a = d.length;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:39:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// int b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:40:8: Context: Field isn't final, but constructor is 'const'.
|
||||
// int? _;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:43:15: Error: Constructor is marked 'const' so all fields must be final.
|
||||
// class const C6(int c, dynamic d) {
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:44:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var a = d.length;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:45:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:46:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var _;
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class C0 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(core::int c, dynamic d) → self::C0
|
||||
: self::C0::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C0::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C1 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C1
|
||||
: self::C1::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C1::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C2 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C2
|
||||
: self::C2::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C2::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C3 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C3
|
||||
: self::C3::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C3::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C4 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C4
|
||||
: self::C4::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C4::b = c, invalid-initializer "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^", invalid-initializer "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:24: Error: 'b' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^"
|
||||
;
|
||||
}
|
||||
class C5 extends core::Object /*hasConstConstructor*/ {
|
||||
field core::int a;
|
||||
field core::int b;
|
||||
field core::int? _ = null;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C5
|
||||
: self::C5::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C5::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C6 extends core::Object /*hasConstConstructor*/ {
|
||||
field dynamic a;
|
||||
field core::int b;
|
||||
field dynamic _ = null;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C6
|
||||
: self::C6::a = d{dynamic}.length, self::C6::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
const self::C0 a = #C3;
|
||||
self::expect(4, #C3.{self::C0::a}{core::int});
|
||||
self::expect(0, #C3.{self::C0::b}{core::int});
|
||||
const self::C1 b = #C6;
|
||||
self::expect(5, #C6.{self::C1::a}{core::int});
|
||||
self::expect(1, #C6.{self::C1::b}{core::int});
|
||||
const self::C2 c = #C9;
|
||||
self::expect(6, #C9.{self::C2::a}{core::int});
|
||||
self::expect(2, #C9.{self::C2::b}{core::int});
|
||||
const self::C3 d = #C12;
|
||||
self::expect(7, #C12.{self::C3::a}{core::int});
|
||||
self::expect(3, #C12.{self::C3::b}{core::int});
|
||||
}
|
||||
static method test() → dynamic {
|
||||
const self::C4 e = invalid-expression "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^";
|
||||
const self::C5 f = #C14;
|
||||
const self::C6 g = #C15;
|
||||
}
|
||||
static method expect(dynamic expected, dynamic actual) → dynamic {
|
||||
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
|
||||
throw "Expected ${expected}, actual ${actual}";
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 4
|
||||
#C2 = 0
|
||||
#C3 = self::C0 {a:#C1, b:#C2}
|
||||
#C4 = 5
|
||||
#C5 = 1
|
||||
#C6 = self::C1 {a:#C4, b:#C5}
|
||||
#C7 = 6
|
||||
#C8 = 2
|
||||
#C9 = self::C2 {a:#C7, b:#C8}
|
||||
#C10 = 7
|
||||
#C11 = 3
|
||||
#C12 = self::C3 {a:#C10, b:#C11}
|
||||
#C13 = null
|
||||
#C14 = self::C5 {a:#C2, b:#C2, _:#C13}
|
||||
#C15 = self::C6 {a:#C2, b:#C2, _:#C13}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_parameters.dart:
|
||||
- C0. (from org-dartlang-testcase:///const_parameters.dart:8:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
|
||||
- C1. (from org-dartlang-testcase:///const_parameters.dart:11:15)
|
||||
- C2. (from org-dartlang-testcase:///const_parameters.dart:16:15)
|
||||
- C3. (from org-dartlang-testcase:///const_parameters.dart:23:15)
|
||||
- C4. (from org-dartlang-testcase:///const_parameters.dart:30:15)
|
||||
- C5. (from org-dartlang-testcase:///const_parameters.dart:37:15)
|
||||
- C6. (from org-dartlang-testcase:///const_parameters.dart:43:15)
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
library;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class C0 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(core::int c, dynamic d) → self::C0
|
||||
: self::C0::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C0::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C1 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C1
|
||||
: self::C1::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C1::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C2 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C2
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C3 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C3
|
||||
: self::C3::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C4 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C4
|
||||
: self::C4::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C4::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C5 extends core::Object /*hasConstConstructor*/ {
|
||||
field core::int a;
|
||||
field core::int b;
|
||||
field core::int? _;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C5
|
||||
: self::C5::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C5::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C6 extends core::Object /*hasConstConstructor*/ {
|
||||
field dynamic a;
|
||||
field core::int b;
|
||||
field dynamic _;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C6
|
||||
: self::C6::a = d{dynamic}.length, self::C6::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method main() → dynamic
|
||||
;
|
||||
static method test() → dynamic
|
||||
;
|
||||
static method expect(dynamic expected, dynamic actual) → dynamic
|
||||
;
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
// this : a = d.length, b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:31:13: Context: 'a' was initialized here.
|
||||
// final int a = d.length;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:24: Error: 'b' is a final instance variable that was initialized at the declaration.
|
||||
// this : a = d.length, b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:32:13: Context: 'b' was initialized here.
|
||||
// final int b = c;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:37:15: Error: Constructor is marked 'const' so all fields must be final.
|
||||
// class const C5(int c, dynamic d) {
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:38:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// int a = d.length;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:39:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// int b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:40:8: Context: Field isn't final, but constructor is 'const'.
|
||||
// int? _;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:43:15: Error: Constructor is marked 'const' so all fields must be final.
|
||||
// class const C6(int c, dynamic d) {
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:44:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var a = d.length;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:45:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var b = c;
|
||||
// ^
|
||||
// pkg/front_end/testcases/primary_constructors/const_parameters.dart:46:7: Context: Field isn't final, but constructor is 'const'.
|
||||
// var _;
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class C0 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(core::int c, dynamic d) → self::C0
|
||||
: self::C0::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C0::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C1 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C1
|
||||
: self::C1::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C1::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C2 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C2
|
||||
: self::C2::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C2::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C3 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C3
|
||||
: self::C3::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C3::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C4 extends core::Object /*hasConstConstructor*/ {
|
||||
final field core::int a;
|
||||
final field core::int b;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C4
|
||||
: self::C4::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C4::b = c, invalid-initializer "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^", invalid-initializer "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:24: Error: 'b' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^"
|
||||
;
|
||||
}
|
||||
class C5 extends core::Object /*hasConstConstructor*/ {
|
||||
field core::int a;
|
||||
field core::int b;
|
||||
field core::int? _ = null;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C5
|
||||
: self::C5::a = d{dynamic}.length as{TypeError,ForDynamic} core::int, self::C5::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C6 extends core::Object /*hasConstConstructor*/ {
|
||||
field dynamic a;
|
||||
field core::int b;
|
||||
field dynamic _ = null;
|
||||
const constructor •(final core::int c, final dynamic d) → self::C6
|
||||
: self::C6::a = d{dynamic}.length, self::C6::b = c, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
const self::C0 a = #C3;
|
||||
self::expect(4, #C3.{self::C0::a}{core::int});
|
||||
self::expect(0, #C3.{self::C0::b}{core::int});
|
||||
const self::C1 b = #C6;
|
||||
self::expect(5, #C6.{self::C1::a}{core::int});
|
||||
self::expect(1, #C6.{self::C1::b}{core::int});
|
||||
const self::C2 c = #C9;
|
||||
self::expect(6, #C9.{self::C2::a}{core::int});
|
||||
self::expect(2, #C9.{self::C2::b}{core::int});
|
||||
const self::C3 d = #C12;
|
||||
self::expect(7, #C12.{self::C3::a}{core::int});
|
||||
self::expect(3, #C12.{self::C3::b}{core::int});
|
||||
}
|
||||
static method test() → dynamic {
|
||||
const self::C4 e = invalid-expression "pkg/front_end/testcases/primary_constructors/const_parameters.dart:34:10: Error: 'a' is a final instance variable that was initialized at the declaration.
|
||||
this : a = d.length, b = c;
|
||||
^";
|
||||
const self::C5 f = #C14;
|
||||
const self::C6 g = #C15;
|
||||
}
|
||||
static method expect(dynamic expected, dynamic actual) → dynamic {
|
||||
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
|
||||
throw "Expected ${expected}, actual ${actual}";
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 4
|
||||
#C2 = 0
|
||||
#C3 = self::C0 {a:#C1, b:#C2}
|
||||
#C4 = 5
|
||||
#C5 = 1
|
||||
#C6 = self::C1 {a:#C4, b:#C5}
|
||||
#C7 = 6
|
||||
#C8 = 2
|
||||
#C9 = self::C2 {a:#C7, b:#C8}
|
||||
#C10 = 7
|
||||
#C11 = 3
|
||||
#C12 = self::C3 {a:#C10, b:#C11}
|
||||
#C13 = null
|
||||
#C14 = self::C5 {a:#C2, b:#C2, _:#C13}
|
||||
#C15 = self::C6 {a:#C2, b:#C2, _:#C13}
|
||||
}
|
||||
|
||||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///const_parameters.dart:
|
||||
- C0. (from org-dartlang-testcase:///const_parameters.dart:8:9)
|
||||
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
|
||||
- C1. (from org-dartlang-testcase:///const_parameters.dart:11:15)
|
||||
- C2. (from org-dartlang-testcase:///const_parameters.dart:16:15)
|
||||
- C3. (from org-dartlang-testcase:///const_parameters.dart:23:15)
|
||||
- C4. (from org-dartlang-testcase:///const_parameters.dart:30:15)
|
||||
- C5. (from org-dartlang-testcase:///const_parameters.dart:37:15)
|
||||
- C6. (from org-dartlang-testcase:///const_parameters.dart:43:15)
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
class C0 {
|
||||
final int a;
|
||||
final int b;
|
||||
const new(int c, dynamic d) : a = d.length, b = c;
|
||||
}
|
||||
|
||||
class const C1(int c, dynamic d) {
|
||||
final int a = d.length;
|
||||
final int b = c;
|
||||
}
|
||||
|
||||
class const C2(int c, dynamic d) {
|
||||
final int a;
|
||||
final int b;
|
||||
this : a = d.length, b = c;
|
||||
}
|
||||
|
||||
class const C3(int c, dynamic d) {
|
||||
final int a = d.length;
|
||||
final int b;
|
||||
this : b = c;
|
||||
}
|
||||
|
||||
class const C4(int c, dynamic d) {
|
||||
final int a = d.length;
|
||||
final int b = c;
|
||||
this : a = d.length, b = c;
|
||||
}
|
||||
|
||||
class const C5(int c, dynamic d) {
|
||||
int a = d.length;
|
||||
int b = c;
|
||||
int? _;
|
||||
}
|
||||
|
||||
class const C6(int c, dynamic d) {
|
||||
var a = d.length;
|
||||
var b = c;
|
||||
var _;
|
||||
}
|
||||
|
||||
main() {}
|
||||
|
||||
test() {}
|
||||
|
||||
expect(expected, actual) {}
|
||||
+4
-4
@@ -43,7 +43,7 @@ class E2<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
|
||||
final field core::Type f;
|
||||
static const field core::List<self::E2<dynamic>> values = const <self::E2<dynamic>>[self::E2::a];
|
||||
const constructor •(core::int #index, core::String #name, final self::E2::T% a, final self::E2::T% b) → self::E2<self::E2::T%>
|
||||
: self::E2::b = b, super core::_Enum::•(#index, #name)
|
||||
: self::E2::d = a, self::E2::e = b, self::E2::f = self::E2::T%, self::E2::b = b, super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method core::_enumToString() → core::String
|
||||
return "E2.${this.{core::_Enum::_name}{core::String}}";
|
||||
@@ -77,6 +77,6 @@ static extension-type-member synthetic method ET2|constructor#_#new#tearOff<T ex
|
||||
Extra constant evaluation status:
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///generic_primary_constructor.dart:30:3 -> InstanceConstant(const E1<int>{E1.b: 1, E1.c: 0, E1.d: 1, E1.f: int, _Enum.index: 0, _Enum._name: "a"})
|
||||
Evaluated: ListLiteral @ org-dartlang-testcase:///generic_primary_constructor.dart:29:6 -> ListConstant(const <E1<dynamic>>[const E1<int>{E1.b: 1, E1.c: 0, E1.d: 1, E1.f: int, _Enum.index: 0, _Enum._name: "a"}])
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///generic_primary_constructor.dart:41:3 -> InstanceConstant(const E2<int>{E2.b: 1, E2.d: null, E2.e: null, E2.f: null, _Enum.index: 0, _Enum._name: "a"})
|
||||
Evaluated: ListLiteral @ org-dartlang-testcase:///generic_primary_constructor.dart:40:6 -> ListConstant(const <E2<dynamic>>[const E2<int>{E2.b: 1, E2.d: null, E2.e: null, E2.f: null, _Enum.index: 0, _Enum._name: "a"}])
|
||||
Extra constant evaluation: evaluated: 25, effectively constant: 4
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///generic_primary_constructor.dart:41:3 -> InstanceConstant(const E2<int>{E2.b: 1, E2.d: 0, E2.e: 1, E2.f: int, _Enum.index: 0, _Enum._name: "a"})
|
||||
Evaluated: ListLiteral @ org-dartlang-testcase:///generic_primary_constructor.dart:40:6 -> ListConstant(const <E2<dynamic>>[const E2<int>{E2.b: 1, E2.d: 0, E2.e: 1, E2.f: int, _Enum.index: 0, _Enum._name: "a"}])
|
||||
Extra constant evaluation: evaluated: 28, effectively constant: 4
|
||||
|
||||
@@ -20,6 +20,7 @@ patterns/pattern_variable_final: FormatterCrash
|
||||
primary_constructors/body_without_primary: FormatterCrash
|
||||
primary_constructors/class_primary_constructor: FormatterCrash
|
||||
primary_constructors/class_primary_declaring_parameters: FormatterCrash
|
||||
primary_constructors/const_parameters: FormatterCrash
|
||||
primary_constructors/const_class: FormatterCrash
|
||||
primary_constructors/duplicate_initialization: FormatterCrash
|
||||
primary_constructors/enum_primary_constructor: FormatterCrash
|
||||
|
||||
Reference in New Issue
Block a user