[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:
Johnni Winther
2026-04-06 23:13:52 -07:00
committed by Commit Queue
parent 0388fb800a
commit 13ecf7c8af
26 changed files with 825 additions and 108 deletions
@@ -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) {
+10 -11
View File
@@ -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) {
+30 -13
View File
@@ -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)
@@ -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)
@@ -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
;
@@ -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)
@@ -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) {}
@@ -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