[cfe] Create constructors through fragments
Change-Id: If2a7095c09dcf2d73d326b6ba6d796acfa882c55
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/408780
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
index 68aa737..0719373 100644
--- a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
@@ -225,7 +225,7 @@
void finalizeInitializingFormal(
DeclarationBuilder declarationBuilder,
- ConstructorDeclaration constructorDeclaration,
+ ConstructorDeclarationBuilder constructorDeclaration,
ClassHierarchyBase hierarchy) {
String fieldName = isWildcardLoweredFormalParameter(name) ? '_' : name;
Builder? fieldBuilder = declarationBuilder.lookupLocalMember(fieldName);
diff --git a/pkg/front_end/lib/src/fragment/constructor.dart b/pkg/front_end/lib/src/fragment/constructor.dart
index 55ce76f..d35939c 100644
--- a/pkg/front_end/lib/src/fragment/constructor.dart
+++ b/pkg/front_end/lib/src/fragment/constructor.dart
@@ -22,7 +22,7 @@
final bool forAbstractClassOrMixin;
Token? _beginInitializers;
- AbstractSourceConstructorBuilder? _builder;
+ SourceConstructorBuilderImpl? _builder;
ConstructorFragment(
{required this.constructorName,
@@ -55,12 +55,12 @@
}
@override
- AbstractSourceConstructorBuilder get builder {
+ SourceConstructorBuilderImpl get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
- void set builder(AbstractSourceConstructorBuilder value) {
+ void set builder(SourceConstructorBuilderImpl value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
}
@@ -91,8 +91,7 @@
// constructor body. An error is reported by the parser but we skip
// the body here to avoid overwriting the already lowering const
// constructor.
- !(_fragment.builder is SourceExtensionTypeConstructorBuilder &&
- _fragment.modifiers.isConst);
+ !(_fragment.builder.isExtensionTypeMember && _fragment.modifiers.isConst);
@override
LocalScope computeFormalParameterScope(LookupScope typeParameterScope) {
diff --git a/pkg/front_end/lib/src/fragment/constructor/declaration.dart b/pkg/front_end/lib/src/fragment/constructor/declaration.dart
new file mode 100644
index 0000000..f0e51ea
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/constructor/declaration.dart
@@ -0,0 +1,677 @@
+// Copyright (c) 2025, 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.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/metadata_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/internal_ast.dart';
+import '../../kernel/kernel_helper.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_constructor_builder.dart';
+import '../../source/source_extension_type_declaration_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../fragment.dart';
+import 'encoding.dart';
+
+abstract class ConstructorDeclaration {
+ List<MetadataBuilder>? get metadata;
+
+ OmittedTypeBuilder get returnType;
+
+ List<NominalParameterBuilder>? get typeParameters;
+
+ List<FormalParameterBuilder>? get formals;
+
+ Member get constructor;
+
+ Procedure? get tearOff;
+
+ FunctionNode get function;
+
+ Member get readTarget;
+
+ Reference get readTargetReference;
+
+ Member get invokeTarget;
+
+ Reference get invokeTargetReference;
+
+ void registerFunctionBody(Statement value);
+
+ void registerNoBodyConstructor();
+
+ VariableDeclaration? get thisVariable;
+
+ List<TypeParameter>? get thisTypeParameters;
+
+ List<Initializer> get initializers;
+
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference});
+
+ void buildOutlineNodes(
+ BuildNodesCallback f, {
+ required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required Member declarationConstructor,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ });
+
+ void prepareInitializers();
+
+ void prependInitializer(Initializer initializer);
+
+ void becomeNative();
+
+ VariableDeclaration? getTearOffParameter(int index);
+
+ void finishAugmentation(SourceConstructorBuilder origin);
+
+ Substitution computeFieldTypeSubstitution(
+ DeclarationBuilder declarationBuilder);
+
+ void buildBody();
+
+ bool get isRedirecting;
+
+ bool get hasSuperInitializingFormals;
+
+ void addSuperParameterDefaultValueCloners(
+ {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ required Member superTarget,
+ required List<int?>? positionalSuperParameters,
+ required List<String>? namedSuperParameters,
+ required SourceLibraryBuilder libraryBuilder});
+}
+
+mixin RegularConstructorDeclarationMixin implements ConstructorDeclaration {
+ RegularConstructorEncoding get _encoding;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member get constructor => _encoding.constructor;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Procedure? get tearOff => _encoding.constructorTearOff;
+
+ @override
+ FunctionNode get function => _encoding.function;
+
+ @override
+ Member get readTarget => _encoding.readTarget;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _encoding.readTargetReference;
+
+ @override
+ Member get invokeTarget => _encoding.invokeTarget;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get invokeTargetReference => _encoding.invokeTargetReference;
+
+ @override
+ void registerFunctionBody(Statement value) {
+ _encoding.registerFunctionBody(value);
+ }
+
+ @override
+ void registerNoBodyConstructor() {
+ _encoding.registerNoBodyConstructor();
+ }
+
+ @override
+ VariableDeclaration? get thisVariable => null;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters => null;
+
+ @override
+ List<Initializer> get initializers => _encoding.initializers;
+
+ @override
+ void prepareInitializers() {
+ _encoding.prepareInitializers();
+ }
+
+ @override
+ void prependInitializer(Initializer initializer) {
+ _encoding.prependInitializer(initializer);
+ }
+
+ @override
+ void becomeNative() {
+ _encoding.becomeNative();
+ }
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) {
+ return _encoding.getTearOffParameter(index);
+ }
+
+ @override
+ void finishAugmentation(SourceConstructorBuilder origin) {
+ _encoding.finishAugmentation(origin);
+ }
+
+ @override
+ Substitution computeFieldTypeSubstitution(
+ DeclarationBuilder declarationBuilder) {
+ // Nothing to substitute. Regular generative constructors don't have their
+ // own type parameters.
+ return Substitution.empty;
+ }
+
+ @override
+ void buildBody() {}
+
+ @override
+ bool get isRedirecting {
+ for (Initializer initializer in initializers) {
+ if (initializer is RedirectingInitializer) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ late final bool hasSuperInitializingFormals =
+ formals?.any((formal) => formal.isSuperInitializingFormal) ?? false;
+
+ @override
+ void addSuperParameterDefaultValueCloners(
+ {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ required Member superTarget,
+ required List<int?>? positionalSuperParameters,
+ required List<String>? namedSuperParameters,
+ required SourceLibraryBuilder libraryBuilder}) {
+ _encoding.addSuperParameterDefaultValueCloners(
+ delayedDefaultValueCloners: delayedDefaultValueCloners,
+ superTarget: superTarget,
+ positionalSuperParameters: positionalSuperParameters,
+ namedSuperParameters: namedSuperParameters,
+ libraryBuilder: libraryBuilder);
+ }
+}
+
+class RegularConstructorDeclaration
+ with RegularConstructorDeclarationMixin
+ implements ConstructorDeclaration {
+ final ConstructorFragment _fragment;
+ final List<FormalParameterBuilder>? _syntheticFormals;
+
+ @override
+ final RegularConstructorEncoding _encoding;
+
+ @override
+ final List<NominalParameterBuilder>? typeParameters;
+
+ RegularConstructorDeclaration(this._fragment,
+ {required List<FormalParameterBuilder>? syntheticFormals,
+ required this.typeParameters})
+ : _syntheticFormals = syntheticFormals,
+ _encoding = new RegularConstructorEncoding(
+ isExternal: _fragment.modifiers.isExternal);
+
+ @override
+ List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+ @override
+ OmittedTypeBuilder get returnType => _fragment.returnType;
+
+ @override
+ late final List<FormalParameterBuilder>? formals = _syntheticFormals != null
+ ? [..._syntheticFormals, ...?_fragment.formals]
+ : _fragment.formals;
+
+ @override
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference}) {
+ _encoding.createNode(
+ name: name,
+ libraryBuilder: libraryBuilder,
+ nameScheme: nameScheme,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ fileUri: _fragment.fileUri,
+ startOffset: _fragment.startOffset,
+ fileOffset: _fragment.fullNameOffset,
+ endOffset: _fragment.endOffset,
+ isSynthetic: false,
+ forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+ }
+
+ @override
+ void buildOutlineNodes(BuildNodesCallback f,
+ {required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required Member declarationConstructor,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+ _encoding.buildOutlineNodes(f,
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder:
+ constructorBuilder.declarationBuilder as SourceClassBuilder,
+ declarationConstructor: declarationConstructor,
+ formalsOffset: _fragment.formalsOffset,
+ isConst: _fragment.modifiers.isConst,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ }
+}
+
+// Coverage-ignore(suite): Not run.
+class PrimaryConstructorDeclaration
+ with RegularConstructorDeclarationMixin
+ implements ConstructorDeclaration {
+ final PrimaryConstructorFragment _fragment;
+
+ @override
+ final RegularConstructorEncoding _encoding;
+
+ PrimaryConstructorDeclaration(this._fragment)
+ : _encoding = new RegularConstructorEncoding(
+ isExternal: _fragment.modifiers.isExternal);
+
+ @override
+ OmittedTypeBuilder get returnType => _fragment.returnType;
+
+ @override
+ List<MetadataBuilder>? get metadata => null;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _fragment.formals;
+
+ @override
+ List<NominalParameterBuilder>? get typeParameters => null;
+
+ @override
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference}) {
+ _encoding.createNode(
+ name: name,
+ libraryBuilder: libraryBuilder,
+ nameScheme: nameScheme,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ fileUri: _fragment.fileUri,
+ startOffset: _fragment.startOffset,
+ fileOffset: _fragment.fileOffset,
+ // TODO(johnniwinther): Provide `endOffset`.
+ endOffset: _fragment.formalsOffset,
+ isSynthetic: false,
+ forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+ }
+
+ @override
+ void buildOutlineNodes(BuildNodesCallback f,
+ {required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required Member declarationConstructor,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+ _encoding.buildOutlineNodes(f,
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder:
+ constructorBuilder.declarationBuilder as SourceClassBuilder,
+ declarationConstructor: declarationConstructor,
+ formalsOffset: _fragment.formalsOffset,
+ isConst: _fragment.modifiers.isConst,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ }
+}
+
+class DefaultEnumConstructorDeclaration
+ with RegularConstructorDeclarationMixin
+ implements ConstructorDeclaration {
+ final Uri _fileUri;
+ final int _fileOffset;
+
+ @override
+ final OmittedTypeBuilder returnType;
+
+ @override
+ final List<FormalParameterBuilder> formals;
+
+ @override
+ final RegularConstructorEncoding _encoding =
+ new RegularConstructorEncoding(isExternal: false);
+
+ DefaultEnumConstructorDeclaration(
+ {required this.returnType,
+ required this.formals,
+ required Uri fileUri,
+ required int fileOffset})
+ : _fileUri = fileUri,
+ _fileOffset = fileOffset;
+
+ @override
+ List<MetadataBuilder>? get metadata => null;
+
+ @override
+ List<NominalParameterBuilder>? get typeParameters => null;
+
+ @override
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference}) {
+ _encoding.createNode(
+ name: name,
+ libraryBuilder: libraryBuilder,
+ nameScheme: nameScheme,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ fileUri: _fileUri,
+ startOffset: _fileOffset,
+ fileOffset: _fileOffset,
+ endOffset: _fileOffset,
+ isSynthetic: true,
+ forAbstractClassOrEnumOrMixin: true);
+ }
+
+ @override
+ void buildOutlineNodes(BuildNodesCallback f,
+ {required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required Member declarationConstructor,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+ _encoding.buildOutlineNodes(f,
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder:
+ constructorBuilder.declarationBuilder as SourceClassBuilder,
+ declarationConstructor: declarationConstructor,
+ formalsOffset: _fileOffset,
+ isConst: true,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ }
+}
+
+mixin ExtensionTypeConstructorDeclarationMixin
+ implements ConstructorDeclaration {
+ ExtensionTypeConstructorEncoding get _encoding;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member get constructor => _encoding.constructor;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Procedure? get tearOff => _encoding.constructorTearOff;
+
+ @override
+ FunctionNode get function => _encoding.function;
+
+ @override
+ Member get readTarget => _encoding.readTarget;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _encoding.readTargetReference;
+
+ @override
+ Member get invokeTarget => _encoding.invokeTarget;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get invokeTargetReference => _encoding.invokeTargetReference;
+
+ @override
+ void registerFunctionBody(Statement value) {
+ _encoding.registerFunctionBody(value);
+ }
+
+ @override
+ void registerNoBodyConstructor() {
+ _encoding.registerNoBodyConstructor();
+ }
+
+ @override
+ VariableDeclaration? get thisVariable => _encoding.thisVariable;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters => _encoding.thisTypeParameters;
+
+ @override
+ List<Initializer> get initializers => _encoding.initializers;
+
+ @override
+ void prepareInitializers() {
+ _encoding.prepareInitializers();
+ }
+
+ @override
+ void prependInitializer(Initializer initializer) {
+ _encoding.prependInitializer(initializer);
+ }
+
+ @override
+ void becomeNative() {
+ throw new UnsupportedError("$runtimeType.becomeNative()");
+ }
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) {
+ return _encoding.getTearOffParameter(index);
+ }
+
+ @override
+ void finishAugmentation(SourceConstructorBuilder origin) {
+ throw new UnsupportedError('$runtimeType.finishAugmentation');
+ }
+
+ @override
+ Substitution computeFieldTypeSubstitution(
+ DeclarationBuilder declarationBuilder) {
+ if (typeParameters != null) {
+ assert(
+ declarationBuilder.typeParameters!.length == typeParameters?.length);
+ return Substitution.fromPairs(
+ (declarationBuilder as SourceExtensionTypeDeclarationBuilder)
+ .extensionTypeDeclaration
+ .typeParameters,
+ new List<DartType>.generate(
+ declarationBuilder.typeParameters!.length,
+ (int index) => new TypeParameterType.withDefaultNullability(
+ function.typeParameters[index])));
+ } else {
+ return Substitution.empty;
+ }
+ }
+
+ @override
+ void buildBody() {
+ _encoding.buildBody();
+ }
+
+ @override
+ bool get isRedirecting {
+ for (Initializer initializer in initializers) {
+ if (initializer is ExtensionTypeRedirectingInitializer) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ late final bool hasSuperInitializingFormals =
+ formals?.any((formal) => formal.isSuperInitializingFormal) ?? false;
+
+ @override
+ void addSuperParameterDefaultValueCloners(
+ {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ required Member superTarget,
+ required List<int?>? positionalSuperParameters,
+ required List<String>? namedSuperParameters,
+ required SourceLibraryBuilder libraryBuilder}) {
+ throw new UnsupportedError(
+ '$runtimeType.addSuperParameterDefaultValueCloners');
+ }
+}
+
+class ExtensionTypeConstructorDeclaration
+ with ExtensionTypeConstructorDeclarationMixin
+ implements ConstructorDeclaration {
+ final ConstructorFragment _fragment;
+
+ @override
+ final List<NominalParameterBuilder>? typeParameters;
+
+ @override
+ final ExtensionTypeConstructorEncoding _encoding;
+
+ ExtensionTypeConstructorDeclaration(this._fragment,
+ {required this.typeParameters})
+ : _encoding = new ExtensionTypeConstructorEncoding(
+ isExternal: _fragment.modifiers.isExternal);
+
+ @override
+ List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+ @override
+ OmittedTypeBuilder get returnType => _fragment.returnType;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _fragment.formals;
+
+ @override
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference}) {
+ _encoding.createNode(
+ name: name,
+ libraryBuilder: libraryBuilder,
+ nameScheme: nameScheme,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ fileUri: _fragment.fileUri,
+ fileOffset: _fragment.fullNameOffset,
+ endOffset: _fragment.endOffset,
+ forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+ }
+
+ @override
+ void buildOutlineNodes(BuildNodesCallback f,
+ {required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required Member declarationConstructor,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+ _encoding.buildOutlineNodes(f,
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: constructorBuilder.declarationBuilder
+ as SourceExtensionTypeDeclarationBuilder,
+ declarationConstructor: declarationConstructor,
+ fileOffset: _fragment.fullNameOffset,
+ formalsOffset: _fragment.formalsOffset,
+ isConst: _fragment.modifiers.isConst,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ }
+}
+
+class ExtensionTypePrimaryConstructorDeclaration
+ with ExtensionTypeConstructorDeclarationMixin
+ implements ConstructorDeclaration {
+ final PrimaryConstructorFragment _fragment;
+
+ @override
+ final List<NominalParameterBuilder>? typeParameters;
+
+ @override
+ final ExtensionTypeConstructorEncoding _encoding;
+
+ ExtensionTypePrimaryConstructorDeclaration(this._fragment,
+ {required this.typeParameters})
+ : _encoding = new ExtensionTypeConstructorEncoding(
+ isExternal: _fragment.modifiers.isExternal);
+
+ @override
+ List<MetadataBuilder>? get metadata => null;
+
+ @override
+ OmittedTypeBuilder get returnType => _fragment.returnType;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _fragment.formals;
+
+ @override
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference}) {
+ _encoding.createNode(
+ name: name,
+ libraryBuilder: libraryBuilder,
+ nameScheme: nameScheme,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ fileUri: _fragment.fileUri,
+ fileOffset: _fragment.fileOffset,
+ // TODO(johnniwinther): Provide `endOffset`.
+ endOffset: _fragment.formalsOffset,
+ forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+ }
+
+ @override
+ void buildOutlineNodes(BuildNodesCallback f,
+ {required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required Member declarationConstructor,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+ _encoding.buildOutlineNodes(f,
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: constructorBuilder.declarationBuilder
+ as SourceExtensionTypeDeclarationBuilder,
+ declarationConstructor: declarationConstructor,
+ fileOffset: _fragment.fileOffset,
+ formalsOffset: _fragment.formalsOffset,
+ isConst: _fragment.modifiers.isConst,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/constructor/encoding.dart b/pkg/front_end/lib/src/fragment/constructor/encoding.dart
new file mode 100644
index 0000000..2ac19d0
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/constructor/encoding.dart
@@ -0,0 +1,564 @@
+// Copyright (c) 2025, 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.
+
+import 'package:kernel/ast.dart';
+
+import '../../api_prototype/lowering_predicates.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/omitted_type_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/constructor_tearoff_lowering.dart';
+import '../../kernel/internal_ast.dart';
+import '../../kernel/kernel_helper.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_constructor_builder.dart';
+import '../../source/source_extension_type_declaration_builder.dart';
+import '../../source/source_function_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../../type_inference/type_schema.dart';
+
+class RegularConstructorEncoding {
+ late final Constructor _constructor;
+
+ late final Procedure? _constructorTearOff;
+
+ final bool _isExternal;
+
+ Statement? bodyInternal;
+
+ RegularConstructorEncoding({required bool isExternal})
+ : _isExternal = isExternal;
+
+ Member get readTarget =>
+ _constructorTearOff ??
+ // The case is need to ensure that the upper bound is [Member] and not
+ // [GenericFunction].
+ _constructor as Member;
+
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference =>
+ (_constructorTearOff ?? _constructor).reference;
+
+ Member get invokeTarget => _constructor;
+
+ // Coverage-ignore(suite): Not run.
+ Reference get invokeTargetReference => _constructor.reference;
+
+ void registerFunctionBody(Statement value) {
+ function.body = value..parent = function;
+ }
+
+ void registerNoBodyConstructor() {
+ if (!_isExternal) {
+ registerFunctionBody(new EmptyStatement());
+ }
+ }
+
+ FunctionNode get function => _constructor.function;
+
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference,
+ required Uri fileUri,
+ required int startOffset,
+ required int fileOffset,
+ required int endOffset,
+ required bool isSynthetic,
+ required bool forAbstractClassOrEnumOrMixin}) {
+ _constructor = new Constructor(
+ new FunctionNode(_isExternal ? null : new EmptyStatement()),
+ name: dummyName,
+ fileUri: fileUri,
+ reference: constructorReference,
+ isSynthetic: isSynthetic)
+ ..startFileOffset = startOffset
+ ..fileOffset = fileOffset
+ ..fileEndOffset = endOffset;
+ nameScheme
+ .getConstructorMemberName(name, isTearOff: false)
+ .attachMember(_constructor);
+ _constructorTearOff = createConstructorTearOffProcedure(
+ nameScheme.getConstructorMemberName(name, isTearOff: true),
+ libraryBuilder,
+ fileUri,
+ fileOffset,
+ tearOffReference,
+ forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin);
+ }
+
+ // Coverage-ignore(suite): Not run.
+ Member get constructor => _constructor;
+
+ // Coverage-ignore(suite): Not run.
+ Procedure? get constructorTearOff => _constructorTearOff;
+
+ List<Initializer> get initializers => _constructor.initializers;
+
+ void buildOutlineNodes(
+ BuildNodesCallback f, {
+ required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required SourceClassBuilder declarationBuilder,
+ required Member declarationConstructor,
+ required int formalsOffset,
+ required bool isConst,
+ required TypeBuilder returnType,
+ required List<NominalParameterBuilder>? typeParameters,
+ required List<FormalParameterBuilder>? formals,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ }) {
+ _build(
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ classBuilder: declarationBuilder,
+ declarationConstructor: declarationConstructor,
+ formalsOffset: formalsOffset,
+ isConst: isConst,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ f(
+ member: _constructor,
+ tearOff: _constructorTearOff,
+ kind: BuiltMemberKind.Constructor);
+ }
+
+ bool _hasBeenBuilt = false;
+
+ void _build({
+ required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required SourceClassBuilder classBuilder,
+ required Member declarationConstructor,
+ required int formalsOffset,
+ required bool isConst,
+ required TypeBuilder returnType,
+ required List<NominalParameterBuilder>? typeParameters,
+ required List<FormalParameterBuilder>? formals,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ }) {
+ if (!_hasBeenBuilt) {
+ // According to the specification §9.3 the return type of a constructor
+ // function is its enclosing class.
+ function.asyncMarker = AsyncMarker.Sync;
+ buildTypeParametersAndFormals(
+ libraryBuilder, function, typeParameters, formals,
+ classTypeParameters: null, supportsTypeParameters: false);
+ Class enclosingClass = classBuilder.cls;
+ List<DartType> typeParameterTypes = <DartType>[];
+ for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
+ TypeParameter typeParameter = enclosingClass.typeParameters[i];
+ typeParameterTypes
+ .add(new TypeParameterType.withDefaultNullability(typeParameter));
+ }
+ InterfaceType type = new InterfaceType(
+ enclosingClass, Nullability.nonNullable, typeParameterTypes);
+ returnType.registerInferredType(type);
+ _constructor.function.fileOffset = formalsOffset;
+ _constructor.function.fileEndOffset = _constructor.fileEndOffset;
+ _constructor.function.typeParameters = const <TypeParameter>[];
+ _constructor.isConst = isConst;
+ _constructor.isExternal = _isExternal;
+
+ if (_constructorTearOff != null) {
+ DelayedDefaultValueCloner delayedDefaultValueCloner =
+ buildConstructorTearOffProcedure(
+ tearOff: _constructorTearOff,
+ declarationConstructor: declarationConstructor,
+ implementationConstructor: _constructor,
+ enclosingDeclarationTypeParameters:
+ classBuilder.cls.typeParameters,
+ libraryBuilder: libraryBuilder);
+ delayedDefaultValueCloners.add(delayedDefaultValueCloner);
+ }
+
+ _hasBeenBuilt = true;
+ }
+ if (formals != null) {
+ bool needsInference = false;
+ for (FormalParameterBuilder formal in formals) {
+ if (formal.type is InferableTypeBuilder &&
+ (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
+ formal.variable!.type = const UnknownType();
+ needsInference = true;
+ } else if (!formal.hasDeclaredInitializer &&
+ formal.isSuperInitializingFormal) {
+ needsInference = true;
+ }
+ }
+ if (needsInference) {
+ libraryBuilder.loader
+ .registerConstructorToBeInferred(_constructor, constructorBuilder);
+ }
+ }
+ }
+
+ void prepareInitializers() {
+ // For const constructors we parse initializers already at the outlining
+ // stage, there is no easy way to make body building stage skip initializer
+ // parsing, so we simply clear parsed initializers and rebuild them
+ // again.
+ // For when doing an experimental incremental compilation they are also
+ // potentially done more than once (because it rebuilds the bodies of an old
+ // 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 = [];
+ //redirectingInitializer = null;
+ //superInitializer = null;
+ }
+
+ void prependInitializer(Initializer initializer) {
+ initializer.parent = _constructor;
+ _constructor.initializers.insert(0, initializer);
+ }
+
+ void becomeNative() {
+ _constructor.isExternal = true;
+ }
+
+ VariableDeclaration? getTearOffParameter(int index) {
+ Procedure? constructorTearOff = _constructorTearOff;
+ if (constructorTearOff != null) {
+ if (index < constructorTearOff.function.positionalParameters.length) {
+ return constructorTearOff.function.positionalParameters[index];
+ } else {
+ index -= constructorTearOff.function.positionalParameters.length;
+ if (index < constructorTearOff.function.namedParameters.length) {
+ return constructorTearOff.function.namedParameters[index];
+ }
+ }
+ }
+ return null;
+ }
+
+ void finishAugmentation(SourceConstructorBuilder origin) {
+ finishConstructorAugmentation(
+ origin.invokeTarget as Constructor, _constructor);
+
+ if (_constructorTearOff != null) {
+ finishProcedureAugmentation(
+ origin.readTarget as Procedure, _constructorTearOff);
+ }
+ }
+
+ bool _hasAddedDefaultValueCloners = false;
+
+ void addSuperParameterDefaultValueCloners(
+ {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ required Member superTarget,
+ required List<int?>? positionalSuperParameters,
+ required List<String>? namedSuperParameters,
+ required SourceLibraryBuilder libraryBuilder}) {
+ if (!_hasAddedDefaultValueCloners) {
+ // If this constructor formals are part of a cyclic dependency this
+ // might be called more than once.
+ delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
+ superTarget, invokeTarget,
+ positionalSuperParameters: positionalSuperParameters ?? const <int>[],
+ namedSuperParameters: namedSuperParameters ?? const <String>[],
+ isOutlineNode: true,
+ libraryBuilder: libraryBuilder));
+ if (_constructorTearOff != null) {
+ delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
+ superTarget, _constructorTearOff,
+ positionalSuperParameters:
+ positionalSuperParameters ?? const <int>[],
+ namedSuperParameters: namedSuperParameters ?? const <String>[],
+ isOutlineNode: true,
+ libraryBuilder: libraryBuilder));
+ }
+ _hasAddedDefaultValueCloners = true;
+ }
+ }
+}
+
+class ExtensionTypeConstructorEncoding {
+ late final Procedure _constructor;
+
+ late final Procedure? _constructorTearOff;
+
+ final bool _isExternal;
+
+ Statement? bodyInternal;
+
+ /// If this procedure is an extension instance member or extension type
+ /// instance member, [_thisVariable] holds the synthetically added `this`
+ /// parameter.
+ VariableDeclaration? _thisVariable;
+
+ /// If this procedure is an extension instance member or extension type
+ /// instance member, [_thisTypeParameters] holds the type parameters copied
+ /// from the extension/extension type declaration.
+ List<TypeParameter>? _thisTypeParameters;
+
+ List<Initializer> initializers = [];
+
+ ExtensionTypeConstructorEncoding({required bool isExternal})
+ : _isExternal = isExternal;
+
+ Member get readTarget =>
+ _constructorTearOff ?? // Coverage-ignore(suite): Not run.
+ _constructor;
+
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference =>
+ (_constructorTearOff ?? _constructor).reference;
+
+ Member get invokeTarget => _constructor;
+
+ // Coverage-ignore(suite): Not run.
+ Reference get invokeTargetReference => _constructor.reference;
+
+ void registerFunctionBody(Statement value) {
+ function.body = value..parent = function;
+ }
+
+ void registerNoBodyConstructor() {
+ if (!_hasBuiltBody && !_isExternal) {
+ registerFunctionBody(new EmptyStatement());
+ }
+ }
+
+ FunctionNode get function => _constructor.function;
+
+ void createNode(
+ {required String name,
+ required SourceLibraryBuilder libraryBuilder,
+ required NameScheme nameScheme,
+ required Reference? constructorReference,
+ required Reference? tearOffReference,
+ required Uri fileUri,
+ required int fileOffset,
+ required int endOffset,
+ required bool forAbstractClassOrEnumOrMixin}) {
+ _constructor = new Procedure(dummyName, ProcedureKind.Method,
+ new FunctionNode(_isExternal ? null : new EmptyStatement()),
+ fileUri: fileUri, reference: constructorReference)
+ ..fileOffset = fileOffset
+ ..fileEndOffset = endOffset;
+ nameScheme
+ .getConstructorMemberName(name, isTearOff: false)
+ .attachMember(_constructor);
+ _constructorTearOff = createConstructorTearOffProcedure(
+ nameScheme.getConstructorMemberName(name, isTearOff: true),
+ libraryBuilder,
+ fileUri,
+ fileOffset,
+ tearOffReference,
+ forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin,
+ forceCreateLowering: true)
+ ?..isExtensionTypeMember = true;
+ }
+
+ // Coverage-ignore(suite): Not run.
+ Member get constructor => _constructor;
+
+ // Coverage-ignore(suite): Not run.
+ Procedure? get constructorTearOff => _constructorTearOff;
+
+ void buildOutlineNodes(
+ BuildNodesCallback f, {
+ required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required SourceExtensionTypeDeclarationBuilder declarationBuilder,
+ required Member declarationConstructor,
+ required int fileOffset,
+ required int formalsOffset,
+ required bool isConst,
+ required TypeBuilder returnType,
+ required List<NominalParameterBuilder>? typeParameters,
+ required List<FormalParameterBuilder>? formals,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ }) {
+ _build(
+ constructorBuilder: constructorBuilder,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: declarationBuilder,
+ declarationConstructor: declarationConstructor,
+ fileOffset: fileOffset,
+ formalsOffset: formalsOffset,
+ isConst: isConst,
+ returnType: returnType,
+ typeParameters: typeParameters,
+ formals: formals,
+ delayedDefaultValueCloners: delayedDefaultValueCloners);
+ f(
+ member: _constructor,
+ tearOff: _constructorTearOff,
+ kind: BuiltMemberKind.ExtensionTypeConstructor);
+ }
+
+ bool _hasBeenBuilt = false;
+
+ void _build({
+ required SourceConstructorBuilder constructorBuilder,
+ required SourceLibraryBuilder libraryBuilder,
+ required SourceExtensionTypeDeclarationBuilder declarationBuilder,
+ required Member declarationConstructor,
+ required int fileOffset,
+ required int formalsOffset,
+ required bool isConst,
+ required TypeBuilder returnType,
+ required List<NominalParameterBuilder>? typeParameters,
+ required List<FormalParameterBuilder>? formals,
+ required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+ }) {
+ if (!_hasBeenBuilt) {
+ // According to the specification §9.3 the return type of a constructor
+ // function is its enclosing class.
+ function.asyncMarker = AsyncMarker.Sync;
+ buildTypeParametersAndFormals(
+ libraryBuilder, function, typeParameters, formals,
+ classTypeParameters: null, supportsTypeParameters: true);
+
+ if (declarationBuilder.typeParameters != null) {
+ int count = declarationBuilder.typeParameters!.length;
+ _thisTypeParameters = new List<TypeParameter>.generate(
+ count, (int index) => function.typeParameters[index],
+ growable: false);
+ }
+ List<DartType> typeArguments;
+ if (_thisTypeParameters != null) {
+ typeArguments = [
+ for (TypeParameter parameter in _thisTypeParameters!)
+ new TypeParameterType.withDefaultNullability(parameter)
+ ];
+ } else {
+ typeArguments = [];
+ }
+
+ ExtensionTypeDeclaration extensionTypeDeclaration =
+ declarationBuilder.extensionTypeDeclaration;
+ _thisVariable = new VariableDeclarationImpl(syntheticThisName,
+ isFinal: true,
+ type: new ExtensionType(
+ extensionTypeDeclaration, Nullability.nonNullable, typeArguments))
+ ..fileOffset = fileOffset
+ ..isLowered = true;
+
+ List<DartType> typeParameterTypes = <DartType>[];
+ for (int i = 0; i < function.typeParameters.length; i++) {
+ TypeParameter typeParameter = function.typeParameters[i];
+ typeParameterTypes
+ .add(new TypeParameterType.withDefaultNullability(typeParameter));
+ }
+ ExtensionType type = new ExtensionType(extensionTypeDeclaration,
+ Nullability.nonNullable, typeParameterTypes);
+ returnType.registerInferredType(type);
+ _constructor.function.fileOffset = formalsOffset;
+ _constructor.function.fileEndOffset = _constructor.fileEndOffset;
+ _constructor.isConst = isConst;
+ _constructor.isExternal = _isExternal;
+ _constructor.isStatic = true;
+ _constructor.isExtensionTypeMember = true;
+
+ if (_constructorTearOff != null) {
+ delayedDefaultValueCloners.add(buildConstructorTearOffProcedure(
+ tearOff: _constructorTearOff,
+ declarationConstructor: declarationConstructor,
+ implementationConstructor: _constructor,
+ libraryBuilder: libraryBuilder));
+ }
+
+ _hasBeenBuilt = true;
+ }
+ if (formals != null) {
+ bool needsInference = false;
+ for (FormalParameterBuilder formal in formals) {
+ if (formal.type is InferableTypeBuilder &&
+ (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
+ formal.variable!.type = const UnknownType();
+ needsInference = true;
+ } else if (!formal.hasDeclaredInitializer &&
+ formal.isSuperInitializingFormal) {
+ needsInference = true;
+ }
+ }
+ if (needsInference) {
+ libraryBuilder.loader
+ .registerConstructorToBeInferred(_constructor, constructorBuilder);
+ }
+ }
+ }
+
+ VariableDeclaration? get thisVariable {
+ assert(_thisVariable != null,
+ "ProcedureBuilder.thisVariable has not been set.");
+ return _thisVariable;
+ }
+
+ List<TypeParameter>? get thisTypeParameters {
+ // Use [_thisVariable] as marker for whether this type parameters have
+ // been computed.
+ assert(_thisVariable != null,
+ "ProcedureBuilder.thisTypeParameters has not been set.");
+ return _thisTypeParameters;
+ }
+
+ void prepareInitializers() {
+ // For const constructors we parse initializers already at the outlining
+ // stage, there is no easy way to make body building stage skip initializer
+ // parsing, so we simply clear parsed initializers and rebuild them
+ // again.
+ // For when doing an experimental incremental compilation they are also
+ // potentially done more than once (because it rebuilds the bodies of an old
+ // 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 = [];
+ //redirectingInitializer = null;
+ //superInitializer = null;
+ }
+
+ void prependInitializer(Initializer initializer) {
+ initializers.insert(0, initializer);
+ }
+
+ VariableDeclaration? getTearOffParameter(int index) {
+ Procedure? constructorTearOff = _constructorTearOff;
+ if (constructorTearOff != null) {
+ if (index < constructorTearOff.function.positionalParameters.length) {
+ return constructorTearOff.function.positionalParameters[index];
+ } else {
+ index -= constructorTearOff.function.positionalParameters.length;
+ if (index < constructorTearOff.function.namedParameters.length) {
+ return constructorTearOff.function.namedParameters[index];
+ }
+ }
+ }
+ return null;
+ }
+
+ bool _hasBuiltBody = false;
+
+ void buildBody() {
+ if (_hasBuiltBody) {
+ return;
+ }
+ if (!_isExternal) {
+ VariableDeclaration thisVariable = this.thisVariable!;
+ List<Statement> statements = [thisVariable];
+ ExtensionTypeInitializerToStatementConverter visitor =
+ new ExtensionTypeInitializerToStatementConverter(
+ statements, thisVariable);
+ for (Initializer initializer in initializers) {
+ initializer.accept(visitor);
+ }
+ if (function.body != null && function.body is! EmptyStatement) {
+ statements.add(function.body!);
+ }
+ statements.add(new ReturnStatement(new VariableGet(thisVariable)));
+ registerFunctionBody(new Block(statements));
+ }
+ _hasBuiltBody = true;
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/getter.dart b/pkg/front_end/lib/src/fragment/getter.dart
index 526b22d..c1e5c65 100644
--- a/pkg/front_end/lib/src/fragment/getter.dart
+++ b/pkg/front_end/lib/src/fragment/getter.dart
@@ -898,7 +898,7 @@
TypeBuilder get returnType => _fragment.returnType;
@override
- void setBody(Statement body) {
+ void registerFunctionBody(Statement body) {
function.body = body..parent = function;
}
diff --git a/pkg/front_end/lib/src/fragment/method.dart b/pkg/front_end/lib/src/fragment/method.dart
index dbe8e64..18525a8 100644
--- a/pkg/front_end/lib/src/fragment/method.dart
+++ b/pkg/front_end/lib/src/fragment/method.dart
@@ -1276,7 +1276,7 @@
TypeBuilder get returnType => _fragment.returnType;
@override
- void setBody(Statement body) {
+ void registerFunctionBody(Statement body) {
function.body = body..parent = function;
}
diff --git a/pkg/front_end/lib/src/fragment/primary_constructor.dart b/pkg/front_end/lib/src/fragment/primary_constructor.dart
index ed22ba3..3f78c8e 100644
--- a/pkg/front_end/lib/src/fragment/primary_constructor.dart
+++ b/pkg/front_end/lib/src/fragment/primary_constructor.dart
@@ -18,7 +18,7 @@
final bool forAbstractClassOrMixin;
Token? _beginInitializers;
- AbstractSourceConstructorBuilder? _builder;
+ SourceConstructorBuilderImpl? _builder;
PrimaryConstructorFragment(
{required this.constructorName,
@@ -47,12 +47,12 @@
}
@override
- AbstractSourceConstructorBuilder get builder {
+ SourceConstructorBuilderImpl get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
- void set builder(AbstractSourceConstructorBuilder value) {
+ void set builder(SourceConstructorBuilderImpl value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
}
diff --git a/pkg/front_end/lib/src/fragment/setter.dart b/pkg/front_end/lib/src/fragment/setter.dart
index 40e0733..38b8b88 100644
--- a/pkg/front_end/lib/src/fragment/setter.dart
+++ b/pkg/front_end/lib/src/fragment/setter.dart
@@ -919,7 +919,7 @@
TypeBuilder get returnType => _fragment.returnType;
@override
- void setBody(Statement body) {
+ void registerFunctionBody(Statement body) {
function.body = body..parent = function;
}
diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart
index 9406f7b..f8ff125 100644
--- a/pkg/front_end/lib/src/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder.dart
@@ -1340,7 +1340,7 @@
])
..fileOffset = body.fileOffset;
}
- _context.setBody(body);
+ _context.registerFunctionBody(body);
}
performBacklogComputations();
@@ -2114,7 +2114,7 @@
/// >If a generative constructor c is not a redirecting constructor
/// >and no body is provided, then c implicitly has an empty body {}.
/// We use an empty statement instead.
- function.body = new EmptyStatement()..parent = function;
+ _context.registerNoBodyConstructor();
} else if (body != null && _context.isMixinClass && !_context.isFactory) {
// Report an error if a mixin class has a non-factory constructor with a
// body.
diff --git a/pkg/front_end/lib/src/kernel/body_builder_context.dart b/pkg/front_end/lib/src/kernel/body_builder_context.dart
index 07216ff..42d0993 100644
--- a/pkg/front_end/lib/src/kernel/body_builder_context.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder_context.dart
@@ -368,8 +368,13 @@
}
/// Registers [body] as the result of the body building.
- void setBody(Statement body) {
- throw new UnsupportedError("${runtimeType}.setBody");
+ void registerFunctionBody(Statement body) {
+ throw new UnsupportedError("${runtimeType}.registerFunctionBody");
+ }
+
+ /// Registers that the constructor has no body.
+ void registerNoBodyConstructor() {
+ throw new UnsupportedError("${runtimeType}.registerNoBodyConstructor");
}
/// Returns the type of `this` in the body being built.
@@ -793,8 +798,8 @@
}
}
-mixin _ConstructorBodyBuilderContextMixin<T extends ConstructorDeclaration>
- implements BodyBuilderContext {
+mixin _ConstructorBodyBuilderContextMixin<
+ T extends ConstructorDeclarationBuilder> implements BodyBuilderContext {
T get _member;
TreeNode get _initializerParent;
@@ -853,11 +858,11 @@
class ConstructorBodyBuilderContext extends BodyBuilderContext
with
- _FunctionBodyBuilderContextMixin<DeclaredSourceConstructorBuilder>,
- _ConstructorBodyBuilderContextMixin<DeclaredSourceConstructorBuilder>,
- _MemberBodyBuilderContext<DeclaredSourceConstructorBuilder> {
+ _FunctionBodyBuilderContextMixin<SourceConstructorBuilderImpl>,
+ _ConstructorBodyBuilderContextMixin<SourceConstructorBuilderImpl>,
+ _MemberBodyBuilderContext<SourceConstructorBuilderImpl> {
@override
- final DeclaredSourceConstructorBuilder _member;
+ final SourceConstructorBuilderImpl _member;
@override
final Member _builtMember;
@@ -872,8 +877,13 @@
}
@override
- void setBody(Statement body) {
- _member.body = body;
+ void registerFunctionBody(Statement body) {
+ _member.registerFunctionBody(body);
+ }
+
+ @override
+ void registerNoBodyConstructor() {
+ _member.registerNoBodyConstructor();
}
@override
@@ -883,7 +893,8 @@
@override
bool needsImplicitSuperInitializer(CoreTypes coreTypes) {
- return !_declarationContext.isObjectClass(coreTypes) &&
+ return _member.isClassMember &&
+ !_declarationContext.isObjectClass(coreTypes) &&
!isExternalConstructor;
}
@@ -891,40 +902,6 @@
TreeNode get _initializerParent => _member.invokeTarget;
}
-class ExtensionTypeConstructorBodyBuilderContext extends BodyBuilderContext
- with
- _FunctionBodyBuilderContextMixin<SourceExtensionTypeConstructorBuilder>,
- _ConstructorBodyBuilderContextMixin<
- SourceExtensionTypeConstructorBuilder>,
- _MemberBodyBuilderContext<SourceExtensionTypeConstructorBuilder> {
- @override
- final SourceExtensionTypeConstructorBuilder _member;
- @override
- final Member _builtMember;
-
- ExtensionTypeConstructorBodyBuilderContext(this._member, this._builtMember)
- : super(_member.libraryBuilder, _member.declarationBuilder,
- isDeclarationInstanceMember: _member.isDeclarationInstanceMember);
-
- @override
- LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
- return _member.computeFormalParameterInitializerScope(parent);
- }
-
- @override
- void setBody(Statement body) {
- _member.body = body;
- }
-
- @override
- bool isConstructorCyclic(String name) {
- return _declarationContext.isConstructorCyclic(_member.name, name);
- }
-
- @override
- TreeNode get _initializerParent => _member.invokeTarget;
-}
-
class ParameterBodyBuilderContext extends BodyBuilderContext {
factory ParameterBodyBuilderContext(
LibraryBuilder libraryBuilder,
diff --git a/pkg/front_end/lib/src/kernel/kernel_target.dart b/pkg/front_end/lib/src/kernel/kernel_target.dart
index 2908382..7df0adb 100644
--- a/pkg/front_end/lib/src/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/kernel/kernel_target.dart
@@ -102,6 +102,14 @@
const PredefinedTypeName("dynamic"), const NullabilityBuilder.inherent(),
instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
+ final NamedTypeBuilder intType = new NamedTypeBuilderImpl(
+ const PredefinedTypeName("int"), const NullabilityBuilder.omitted(),
+ instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
+
+ final NamedTypeBuilder stringType = new NamedTypeBuilderImpl(
+ const PredefinedTypeName("String"), const NullabilityBuilder.omitted(),
+ instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
+
final NamedTypeBuilder objectType = new NamedTypeBuilderImpl(
const PredefinedTypeName("Object"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
@@ -1232,30 +1240,25 @@
enclosingClass.enclosingLibrary.nonNullable, typeParameterTypes);
}
+ void _bindCoreType(NamedTypeBuilder typeBuilder, {bool isNullClass = false}) {
+ TypeDeclarationBuilder typeDeclarationBuilder = loader.coreLibrary
+ .lookupLocalMember(typeBuilder.typeName.name, required: true)
+ as TypeDeclarationBuilder;
+ typeBuilder.bind(loader.coreLibrary, typeDeclarationBuilder);
+ if (isNullClass) {
+ (typeDeclarationBuilder as ClassBuilder).isNullClass = true;
+ }
+ }
+
void setupTopAndBottomTypes() {
- objectType.bind(
- loader.coreLibrary,
- loader.coreLibrary.lookupLocalMember("Object", required: true)
- as TypeDeclarationBuilder);
- dynamicType.bind(
- loader.coreLibrary,
- loader.coreLibrary.lookupLocalMember("dynamic", required: true)
- as TypeDeclarationBuilder);
- ClassBuilder nullClassBuilder = loader.coreLibrary
- .lookupLocalMember("Null", required: true) as ClassBuilder;
- nullType.bind(loader.coreLibrary, nullClassBuilder..isNullClass = true);
- bottomType.bind(
- loader.coreLibrary,
- loader.coreLibrary.lookupLocalMember("Never", required: true)
- as TypeDeclarationBuilder);
- enumType.bind(
- loader.coreLibrary,
- loader.coreLibrary.lookupLocalMember("Enum", required: true)
- as TypeDeclarationBuilder);
- underscoreEnumType.bind(
- loader.coreLibrary,
- loader.coreLibrary.lookupLocalMember("_Enum", required: true)
- as TypeDeclarationBuilder);
+ _bindCoreType(objectType);
+ _bindCoreType(stringType);
+ _bindCoreType(intType);
+ _bindCoreType(dynamicType);
+ _bindCoreType(nullType, isNullClass: true);
+ _bindCoreType(bottomType);
+ _bindCoreType(enumType);
+ _bindCoreType(underscoreEnumType);
}
void computeCoreTypes() {
@@ -1421,15 +1424,16 @@
}
}
- Map<ConstructorDeclaration, Set<SourcePropertyBuilder>>
+ Map<ConstructorDeclarationBuilder, Set<SourcePropertyBuilder>>
constructorInitializedFields = new Map.identity();
Set<SourcePropertyBuilder>? initializedFieldBuilders = null;
Set<SourcePropertyBuilder>? uninitializedInstanceFields;
- Iterator<ConstructorDeclaration> constructorIterator =
- classDeclaration.fullConstructorIterator<ConstructorDeclaration>();
+ Iterator<ConstructorDeclarationBuilder> constructorIterator =
+ classDeclaration
+ .fullConstructorIterator<ConstructorDeclarationBuilder>();
while (constructorIterator.moveNext()) {
- ConstructorDeclaration constructor = constructorIterator.current;
+ ConstructorDeclarationBuilder constructor = constructorIterator.current;
if (constructor.isEffectivelyRedirecting) continue;
if (constructor.isConst && nonFinalFields.isNotEmpty) {
classDeclaration.addProblem(messageConstConstructorNonFinalField,
@@ -1514,9 +1518,10 @@
// Run through all fields that are initialized by some constructor, and
// make sure that all other constructors also initialize them.
- for (MapEntry<ConstructorDeclaration, Set<SourcePropertyBuilder>> entry
+ for (MapEntry<ConstructorDeclarationBuilder,
+ Set<SourcePropertyBuilder>> entry
in constructorInitializedFields.entries) {
- ConstructorDeclaration constructorBuilder = entry.key;
+ ConstructorDeclarationBuilder constructorBuilder = entry.key;
Set<SourcePropertyBuilder> fieldBuilders = entry.value;
for (SourcePropertyBuilder fieldBuilder
in initializedFieldBuilders!.difference(fieldBuilders)) {
diff --git a/pkg/front_end/lib/src/source/constructor_declaration.dart b/pkg/front_end/lib/src/source/constructor_declaration.dart
index c679343..47f64e1 100644
--- a/pkg/front_end/lib/src/source/constructor_declaration.dart
+++ b/pkg/front_end/lib/src/source/constructor_declaration.dart
@@ -12,7 +12,7 @@
/// Common interface for builders for generative constructor declarations in
/// source code, such as a generative constructor in a regular class or a
/// generative constructor in an extension type declaration.
-abstract class ConstructorDeclaration implements SourceFunctionBuilder {
+abstract class ConstructorDeclarationBuilder implements SourceFunctionBuilder {
/// Returns `true` if this constructor, including its augmentations, is
/// external.
///
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart
index 5e50ac4..b356df5 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -940,7 +940,7 @@
SourceMemberBuilder constructor = constructorIterator.current;
// Assumes the constructor isn't synthetic since
// [installSyntheticConstructors] hasn't been called yet.
- if (constructor is DeclaredSourceConstructorBuilder) {
+ if (constructor is SourceConstructorBuilderImpl) {
// Report an error if a mixin class has a constructor with parameters,
// is external, or is a redirecting constructor.
if (constructor.isRedirecting ||
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart
index c7356eb..20fd2bc 100644
--- a/pkg/front_end/lib/src/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -8,7 +8,6 @@
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
-import '../api_prototype/lowering_predicates.dart';
import '../base/constant_context.dart' show ConstantContext;
import '../base/identifiers.dart';
import '../base/local_scope.dart';
@@ -33,27 +32,20 @@
import '../builder/metadata_builder.dart';
import '../builder/omitted_type_builder.dart';
import '../builder/type_builder.dart';
+import '../fragment/constructor/declaration.dart';
import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/body_builder_context.dart';
-import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/expression_generator_helper.dart';
import '../kernel/hierarchy/class_member.dart' show ClassMember;
import '../kernel/internal_ast.dart';
import '../kernel/kernel_helper.dart'
- show
- DelayedDefaultValueCloner,
- TypeDependency,
- finishConstructorAugmentation,
- finishProcedureAugmentation;
+ show DelayedDefaultValueCloner, TypeDependency;
import '../kernel/type_algorithms.dart';
import '../type_inference/inference_results.dart';
-import '../type_inference/type_schema.dart';
import 'constructor_declaration.dart';
import 'name_scheme.dart';
-import 'source_builder_mixins.dart';
import 'source_class_builder.dart';
import 'source_enum_builder.dart';
-import 'source_extension_type_declaration_builder.dart';
import 'source_function_builder.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
import 'source_loader.dart'
@@ -85,56 +77,66 @@
Uri get fileUri;
}
-abstract class AbstractSourceConstructorBuilder extends SourceMemberBuilderImpl
+class SourceConstructorBuilderImpl extends SourceMemberBuilderImpl
implements
SourceConstructorBuilder,
SourceFunctionBuilder,
Inferable,
- ConstructorDeclaration,
+ ConstructorDeclarationBuilder,
InferredTypeListener {
- @override
- final List<MetadataBuilder>? metadata;
-
final Modifiers modifiers;
@override
final String name;
@override
- final List<NominalParameterBuilder>? typeParameters;
+ final SourceLibraryBuilder libraryBuilder;
@override
- final List<FormalParameterBuilder>? formals;
-
- /// If this procedure is an extension instance member or extension type
- /// instance member, [_thisVariable] holds the synthetically added `this`
- /// parameter.
- VariableDeclaration? _thisVariable;
-
- /// If this procedure is an extension instance member or extension type
- /// instance member, [_thisTypeParameters] holds the type parameters copied
- /// from the extension/extension type declaration.
- List<TypeParameter>? _thisTypeParameters;
+ final DeclarationBuilder declarationBuilder;
@override
- final OmittedTypeBuilder returnType;
+ final int fileOffset;
- final int charOpenParenOffset;
-
- bool _hasFormalsInferred = false;
+ @override
+ final Uri fileUri;
Token? beginInitializers;
- AbstractSourceConstructorBuilder(
- this.metadata,
- this.modifiers,
- this.returnType,
- this.name,
- this.typeParameters,
- this.formals,
- this.charOpenParenOffset,
- this.nativeMethodName,
- this.beginInitializers) {
+ final ConstructorDeclaration _introductory;
+
+ final MemberName _memberName;
+
+ final List<DelayedDefaultValueCloner> _delayedDefaultValueCloners = [];
+
+ Set<SourcePropertyBuilder>? _initializedFields;
+
+ SourceConstructorBuilderImpl? actualOrigin;
+
+ List<SourceConstructorBuilderImpl>? _augmentations;
+
+ SourceConstructorBuilderImpl({
+ required this.modifiers,
+ required this.name,
+ required this.libraryBuilder,
+ required this.declarationBuilder,
+ required this.fileOffset,
+ required this.fileUri,
+ this.nativeMethodName,
+ required Reference? constructorReference,
+ required Reference? tearOffReference,
+ required NameScheme nameScheme,
+ required this.beginInitializers,
+ required ConstructorDeclaration constructorDeclaration,
+ }) : _introductory = constructorDeclaration,
+ _memberName = nameScheme.getDeclaredName(name) {
+ _introductory.createNode(
+ name: name,
+ libraryBuilder: libraryBuilder,
+ nameScheme: nameScheme,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference);
+
returnType.registerInferredTypeListener(this);
if (formals != null) {
for (FormalParameterBuilder formal in formals!) {
@@ -146,6 +148,22 @@
}
@override
+ Builder get parent => declarationBuilder;
+
+ @override
+ List<MetadataBuilder>? get metadata => _introductory.metadata;
+
+ @override
+ OmittedTypeBuilder get returnType => _introductory.returnType;
+
+ @override
+ List<NominalParameterBuilder>? get typeParameters =>
+ _introductory.typeParameters;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _introductory.formals;
+
+ @override
// Coverage-ignore(suite): Not run.
Iterable<MetadataBuilder>? get metadataForTesting => metadata;
@@ -171,9 +189,119 @@
// Coverage-ignore(suite): Not run.
bool get isAssignable => false;
+ @override
+ // Coverage-ignore(suite): Not run.
+ Name get memberName => _memberName.name;
+
/// Returns `true` if this member is augmented, either by being the origin
/// of a augmented member or by not being the last among augmentations.
- bool get isAugmented;
+ bool get isAugmented {
+ if (isAugmenting) {
+ return origin._augmentations!.last != this;
+ } else {
+ return _augmentations != null;
+ }
+ }
+
+ @override
+ SourceConstructorBuilderImpl get origin => actualOrigin ?? this;
+
+ // Coverage-ignore(suite): Not run.
+ List<SourceConstructorBuilder>? get augmentationsForTesting => _augmentations;
+
+ @override
+ void applyAugmentation(Builder augmentation) {
+ if (augmentation is SourceConstructorBuilderImpl) {
+ if (checkAugmentation(
+ augmentationLibraryBuilder: augmentation.libraryBuilder,
+ origin: this,
+ augmentation: augmentation)) {
+ augmentation.actualOrigin = this;
+ (_augmentations ??= []).add(augmentation);
+ }
+ } else {
+ // Coverage-ignore-block(suite): Not run.
+ reportAugmentationMismatch(
+ originLibraryBuilder: libraryBuilder,
+ origin: this,
+ augmentation: augmentation);
+ }
+ }
+
+ @override
+ bool get isRedirecting => _introductory.isRedirecting;
+
+ @override
+ VariableDeclaration? get thisVariable => _introductory.thisVariable;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters =>
+ _introductory.thisTypeParameters;
+
+ @override
+ Member get readTarget => _introductory.readTarget;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _introductory.readTargetReference;
+
+ @override
+ Member get invokeTarget =>
+ isAugmenting ? origin.invokeTarget : _introductory.invokeTarget;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get invokeTargetReference => isAugmenting
+ ? origin.invokeTargetReference
+ : _introductory.invokeTargetReference;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member? get writeTarget => null;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get writeTargetReference => null;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Reference> get exportedMemberReferences => [invokeTargetReference];
+
+ // TODO(johnniwinther): Add annotations to tear-offs.
+ @override
+ Iterable<Annotatable> get annotatables => [invokeTarget];
+
+ @override
+ FunctionNode get function => _introductory.function;
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ _introductory.becomeNative();
+ for (Annotatable annotatable in annotatables) {
+ loader.addNativeAnnotation(annotatable, nativeMethodName!);
+ }
+ }
+
+ late final Substitution _fieldTypeSubstitution =
+ _introductory.computeFieldTypeSubstitution(declarationBuilder);
+
+ @override
+ DartType substituteFieldType(DartType fieldType) {
+ return _fieldTypeSubstitution.substituteType(fieldType);
+ }
+
+ void registerFunctionBody(Statement value) {
+ _introductory.registerFunctionBody(value);
+ }
+
+ void registerNoBodyConstructor() {
+ _introductory.registerNoBodyConstructor();
+ }
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) {
+ return _introductory.getTearOffParameter(index);
+ }
LocalScope computeFormalParameterScope(LookupScope parent) {
if (formals == null) return new FormalParameterScope(parent: parent);
@@ -255,275 +383,38 @@
final String? nativeMethodName;
- Statement? bodyInternal;
-
- void set body(Statement? newBody) {
-// if (newBody != null) {
-// if (isAbstract) {
-// // TODO(danrubel): Is this check needed?
-// return internalProblem(messageInternalProblemBodyOnAbstractMethod,
-// newBody.fileOffset, fileUri);
-// }
-// }
- bodyInternal = newBody;
- // A forwarding semi-stub is a method that is abstract in the source code,
- // but which needs to have a forwarding stub body in order to ensure that
- // covariance checks occur. We don't want to replace the forwarding stub
- // body with null.
- TreeNode? parent = function.parent;
- if (!(newBody == null &&
- // Coverage-ignore(suite): Not run.
- parent is Procedure &&
- // Coverage-ignore(suite): Not run.
- parent.isForwardingSemiStub)) {
- function.body = newBody;
- newBody?.parent = function;
- }
- }
-
@override
// Coverage-ignore(suite): Not run.
bool get isNative => nativeMethodName != null;
- bool get supportsTypeParameters => true;
-
- void buildFunction() {
- function.asyncMarker = AsyncMarker.Sync;
- function.body = body;
- body?.parent = function;
- buildTypeParametersAndFormals(
- libraryBuilder, function, typeParameters, formals,
- classTypeParameters: null,
- supportsTypeParameters: supportsTypeParameters);
- if (!(isExtensionInstanceMember || isExtensionTypeInstanceMember) &&
- isSetter &&
- // Coverage-ignore(suite): Not run.
- (formals?.length != 1 || formals![0].isOptionalPositional)) {
- // Coverage-ignore-block(suite): Not run.
- // Replace illegal parameters by single dummy parameter.
- // Do this after building the parameters, since the diet listener
- // assumes that parameters are built, even if illegal in number.
- VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
- function.positionalParameters.clear();
- function.positionalParameters.add(parameter);
- parameter.parent = function;
- function.namedParameters.clear();
- function.requiredParameterCount = 1;
- } else if ((isExtensionInstanceMember || isExtensionTypeInstanceMember) &&
- isSetter &&
- // Coverage-ignore(suite): Not run.
- (formals?.length != 2 || formals![1].isOptionalPositional)) {
- // Coverage-ignore-block(suite): Not run.
- // Replace illegal parameters by single dummy parameter (after #this).
- // Do this after building the parameters, since the diet listener
- // assumes that parameters are built, even if illegal in number.
- VariableDeclaration thisParameter = function.positionalParameters[0];
- VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
- function.positionalParameters.clear();
- function.positionalParameters.add(thisParameter);
- function.positionalParameters.add(parameter);
- parameter.parent = function;
- function.namedParameters.clear();
- function.requiredParameterCount = 2;
- }
- if (returnType is! InferableTypeBuilder) {
- // Coverage-ignore-block(suite): Not run.
- function.returnType =
- returnType.build(libraryBuilder, TypeUse.returnType);
- }
- if (isExtensionInstanceMember || isExtensionTypeInstanceMember) {
- SourceDeclarationBuilderMixin declarationBuilder =
- parent as SourceDeclarationBuilderMixin;
- if (declarationBuilder.typeParameters != null) {
- int count = declarationBuilder.typeParameters!.length;
- _thisTypeParameters = new List<TypeParameter>.generate(
- count, (int index) => function.typeParameters[index],
- growable: false);
- }
- if (isExtensionTypeInstanceMember && isConstructor) {
- SourceExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder =
- parent as SourceExtensionTypeDeclarationBuilder;
- List<DartType> typeArguments;
- if (_thisTypeParameters != null) {
- typeArguments = [
- for (TypeParameter parameter in _thisTypeParameters!)
- new TypeParameterType.withDefaultNullability(parameter)
- ];
- } else {
- typeArguments = [];
- }
- _thisVariable = new VariableDeclarationImpl(syntheticThisName,
- isFinal: true,
- type: new ExtensionType(
- extensionTypeDeclarationBuilder.extensionTypeDeclaration,
- Nullability.nonNullable,
- typeArguments))
- ..fileOffset = fileOffset
- ..isLowered = true;
- } else {
- // Coverage-ignore-block(suite): Not run.
- _thisVariable = function.positionalParameters.first;
- }
- }
- }
-
- @override
- VariableDeclaration getFormalParameter(int index) {
- return formals![index].variable!;
- }
-
- @override
- VariableDeclaration? get thisVariable {
- assert(
- _thisVariable != null ||
- !(isExtensionInstanceMember || isExtensionTypeInstanceMember),
- "ProcedureBuilder.thisVariable has not been set.");
- return _thisVariable;
- }
-
- @override
- List<TypeParameter>? get thisTypeParameters {
- // Use [_thisVariable] as marker for whether this type parameters have
- // been computed.
- assert(
- _thisVariable != null ||
- !(isExtensionInstanceMember || isExtensionTypeInstanceMember),
- "ProcedureBuilder.thisTypeParameters has not been set.");
- return _thisTypeParameters;
- }
-
@override
void onInferredType(DartType type) {
function.returnType = type;
}
- bool hasBuiltOutlineExpressions = false;
-
- @override
- void buildOutlineExpressions(ClassHierarchy classHierarchy,
- List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
- if (!hasBuiltOutlineExpressions) {
- formals?.infer(classHierarchy);
-
- DeclarationBuilder? classOrExtensionBuilder =
- isClassMember || isExtensionMember || isExtensionTypeMember
- ? parent as DeclarationBuilder
- : null;
- LookupScope parentScope =
- classOrExtensionBuilder?.scope ?? // Coverage-ignore(suite): Not run.
- libraryBuilder.scope;
- for (Annotatable annotatable in annotatables) {
- MetadataBuilder.buildAnnotations(annotatable, metadata,
- createBodyBuilderContext(), libraryBuilder, fileUri, parentScope,
- createFileUriExpression: isAugmented);
- }
- if (typeParameters != null) {
- for (int i = 0; i < typeParameters!.length; i++) {
- typeParameters![i].buildOutlineExpressions(
- libraryBuilder,
- createBodyBuilderContext(),
- classHierarchy,
- computeTypeParameterScope(parentScope));
- }
- }
-
- if (formals != null) {
- // For const constructors we need to include default parameter values
- // into the outline. For all other formals we need to call
- // buildOutlineExpressions to clear initializerToken to prevent
- // consuming too much memory.
- for (FormalParameterBuilder formal in formals!) {
- formal.buildOutlineExpressions(libraryBuilder, declarationBuilder,
- buildDefaultValue: FormalParameterBuilder
- .needsDefaultValuesBuiltAsOutlineExpressions(this));
- }
- }
- hasBuiltOutlineExpressions = true;
- }
- }
-
- @override
- void becomeNative(SourceLoader loader) {
- for (Annotatable annotatable in annotatables) {
- loader.addNativeAnnotation(annotatable, nativeMethodName!);
- }
- }
-
- BodyBuilderContext createBodyBuilderContext();
-
@override
bool get isConstructor => true;
- Statement? get body {
- if (bodyInternal == null && !isExternal) {
- bodyInternal = new EmptyStatement();
- }
- return bodyInternal;
- }
+ List<Initializer> get _initializers => _introductory.initializers;
- @override
- void inferTypes(ClassHierarchyBase hierarchy) {
- inferFormalTypes(hierarchy);
- }
-
- @override
- void inferFormalTypes(ClassHierarchyBase hierarchy) {
- if (_hasFormalsInferred) return;
- if (formals != null) {
- libraryBuilder.loader.withUriForCrashReporting(fileUri, fileOffset, () {
- for (FormalParameterBuilder formal in formals!) {
- if (formal.type is InferableTypeBuilder) {
- if (formal.isInitializingFormal) {
- formal.finalizeInitializingFormal(
- declarationBuilder, this, hierarchy);
- }
- }
- }
- _inferSuperInitializingFormals(hierarchy);
- });
- }
- _hasFormalsInferred = true;
- }
-
- // Coverage-ignore(suite): Not run.
- void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {}
-
- void _buildFormals(Member member) {
- if (formals != null) {
- bool needsInference = false;
- for (FormalParameterBuilder formal in formals!) {
- if (formal.type is InferableTypeBuilder &&
- (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
- formal.variable!.type = const UnknownType();
- needsInference = true;
- } else if (!formal.hasDeclaredInitializer &&
- formal.isSuperInitializingFormal) {
- needsInference = true;
- }
- }
- if (needsInference) {
- libraryBuilder.loader.registerConstructorToBeInferred(member, this);
- }
- }
- }
-
- List<Initializer> get initializers;
-
- void _injectInvalidInitializer(Message message, int charOffset, int length,
- ExpressionGeneratorHelper helper, TreeNode parent) {
- Initializer lastInitializer = initializers.removeLast();
- assert(lastInitializer == superInitializer ||
- lastInitializer == redirectingInitializer);
- Initializer error = helper.buildInvalidInitializer(
- helper.buildProblem(message, charOffset, length));
- initializers.add(error..parent = parent);
- initializers.add(lastInitializer);
- }
+ List<Initializer> get initializers =>
+ isAugmenting ? origin.initializers : _initializers;
SuperInitializer? superInitializer;
RedirectingInitializer? redirectingInitializer;
+ void _injectInvalidInitializer(Message message, int charOffset, int length,
+ ExpressionGeneratorHelper helper, TreeNode parent) {
+ Initializer lastInitializer = _introductory.initializers.removeLast();
+ assert(lastInitializer == superInitializer ||
+ lastInitializer == redirectingInitializer);
+ Initializer error = helper.buildInvalidInitializer(
+ helper.buildProblem(message, charOffset, length));
+ _initializers.add(error..parent = parent);
+ _initializers.add(lastInitializer);
+ }
+
@override
void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
{required InitializerInferenceResult? inferenceResult,
@@ -540,7 +431,7 @@
helper,
parent);
} else {
- inferenceResult?.applyResult(initializers, parent);
+ inferenceResult?.applyResult(_initializers, parent);
superInitializer = initializer;
LocatedMessage? message = helper.checkArgumentsForFunction(
@@ -548,7 +439,7 @@
initializer.arguments,
initializer.arguments.fileOffset, <TypeParameter>[]);
if (message != null) {
- initializers.add(helper.buildInvalidInitializer(
+ _initializers.add(helper.buildInvalidInitializer(
helper.buildUnresolvedError(
helper.constructorNameForDiagnostics(
initializer.target.name.text),
@@ -559,7 +450,7 @@
kind: UnresolvedKind.Constructor))
..parent = parent);
} else {
- initializers.add(initializer..parent = parent);
+ _initializers.add(initializer..parent = parent);
}
}
} else if (initializer is RedirectingInitializer) {
@@ -578,10 +469,10 @@
noLength,
helper,
parent);
- } else if (initializers.isNotEmpty) {
+ } else if (_initializers.isNotEmpty) {
// Error on all previous ones.
- for (int i = 0; i < initializers.length; i++) {
- Initializer initializer = initializers[i];
+ for (int i = 0; i < _initializers.length; i++) {
+ Initializer initializer = _initializers[i];
int length = noLength;
if (initializer is AssertInitializer) length = "assert".length;
Initializer error = helper.buildInvalidInitializer(
@@ -590,13 +481,13 @@
initializer.fileOffset,
length));
error.parent = parent;
- initializers[i] = error;
+ _initializers[i] = error;
}
- inferenceResult?.applyResult(initializers, parent);
- initializers.add(initializer..parent = parent);
+ inferenceResult?.applyResult(_initializers, parent);
+ _initializers.add(initializer..parent = parent);
redirectingInitializer = initializer;
} else {
- inferenceResult?.applyResult(initializers, parent);
+ inferenceResult?.applyResult(_initializers, parent);
redirectingInitializer = initializer;
LocatedMessage? message = helper.checkArgumentsForFunction(
@@ -604,7 +495,7 @@
initializer.arguments,
initializer.arguments.fileOffset, const <TypeParameter>[]);
if (message != null) {
- initializers.add(helper.buildInvalidInitializer(
+ _initializers.add(helper.buildInvalidInitializer(
helper.buildUnresolvedError(
helper.constructorNameForDiagnostics(
initializer.target.name.text),
@@ -615,7 +506,7 @@
kind: UnresolvedKind.Constructor))
..parent = parent);
} else {
- initializers.add(initializer..parent = parent);
+ _initializers.add(initializer..parent = parent);
}
}
} else if (redirectingInitializer != null) {
@@ -631,8 +522,8 @@
_injectInvalidInitializer(messageSuperInitializerNotLast,
initializer.fileOffset, noLength, helper, parent);
} else {
- inferenceResult?.applyResult(initializers, parent);
- initializers.add(initializer..parent = parent);
+ inferenceResult?.applyResult(_initializers, parent);
+ _initializers.add(initializer..parent = parent);
}
}
@@ -662,24 +553,6 @@
}
}
- Procedure? get _constructorTearOff;
-
- @override
- VariableDeclaration? getTearOffParameter(int index) {
- Procedure? constructorTearOff = _constructorTearOff;
- if (constructorTearOff != null) {
- if (index < constructorTearOff.function.positionalParameters.length) {
- return constructorTearOff.function.positionalParameters[index];
- } else {
- index -= constructorTearOff.function.positionalParameters.length;
- if (index < constructorTearOff.function.namedParameters.length) {
- return constructorTearOff.function.namedParameters[index];
- }
- }
- }
- return null;
- }
-
@override
int computeDefaultTypes(ComputeDefaultTypeContext context,
{required bool inErrorRecovery}) {
@@ -701,6 +574,12 @@
TypeEnvironment typeEnvironment) {
library.checkInitializersInFormals(formals, typeEnvironment,
isAbstract: isAbstract, isExternal: isExternal);
+ List<SourceConstructorBuilderImpl>? augmentations = _augmentations;
+ if (augmentations != null) {
+ for (SourceConstructorBuilderImpl augmentation in augmentations) {
+ augmentation.checkTypes(library, nameSpace, typeEnvironment);
+ }
+ }
}
@override
@@ -745,27 +624,121 @@
@override
// Coverage-ignore(suite): Not run.
bool get isEnumElement => false;
-}
-
-class DeclaredSourceConstructorBuilder
- extends AbstractSourceConstructorBuilder {
- late final Constructor _constructor;
@override
- late final Procedure? _constructorTearOff;
-
- Set<SourcePropertyBuilder>? _initializedFields;
-
- DeclaredSourceConstructorBuilder? actualOrigin;
-
- List<DeclaredSourceConstructorBuilder>? _augmentations;
-
- bool _hasDefaultValueCloner = false;
+ void buildOutlineNodes(BuildNodesCallback f) {
+ _introductory.buildOutlineNodes(f,
+ constructorBuilder: this,
+ libraryBuilder: libraryBuilder,
+ declarationConstructor: invokeTarget,
+ delayedDefaultValueCloners: _delayedDefaultValueCloners);
+ }
@override
- List<FormalParameterBuilder>? formals;
+ int buildBodyNodes(BuildNodesCallback f) {
+ _introductory.buildBody();
+ if (!isAugmenting) return 0;
+ _introductory.finishAugmentation(origin);
+ return 1;
+ }
- final MemberName _memberName;
+ @override
+ void registerInitializedField(SourcePropertyBuilder fieldBuilder) {
+ if (isAugmenting) {
+ origin.registerInitializedField(fieldBuilder);
+ } else {
+ (_initializedFields ??= {}).add(fieldBuilder);
+ }
+ }
+
+ @override
+ Set<SourcePropertyBuilder>? takeInitializedFields() {
+ Set<SourcePropertyBuilder>? result = _initializedFields;
+ _initializedFields = null;
+ return result;
+ }
+
+ @override
+ void prepareInitializers() {
+ _introductory.prepareInitializers();
+ redirectingInitializer = null;
+ superInitializer = null;
+ }
+
+ @override
+ void prependInitializer(Initializer initializer) {
+ if (isAugmentation) {
+ // Coverage-ignore-block(suite): Not run.
+ origin.prependInitializer(initializer);
+ } else {
+ _introductory.prependInitializer(initializer);
+ }
+ }
+
+ bool _hasBuiltOutlines = false;
+ bool hasBuiltOutlineExpressions = false;
+
+ @override
+ void buildOutlineExpressions(ClassHierarchy classHierarchy,
+ List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
+ if (_hasBuiltOutlines) return;
+
+ if (isConst && isAugmenting) {
+ origin.buildOutlineExpressions(
+ classHierarchy, delayedDefaultValueCloners);
+ }
+ if (!hasBuiltOutlineExpressions) {
+ formals?.infer(classHierarchy);
+
+ LookupScope parentScope = declarationBuilder.scope;
+ for (Annotatable annotatable in annotatables) {
+ MetadataBuilder.buildAnnotations(annotatable, metadata,
+ createBodyBuilderContext(), libraryBuilder, fileUri, parentScope,
+ createFileUriExpression: isAugmented);
+ }
+ if (typeParameters != null) {
+ for (int i = 0; i < typeParameters!.length; i++) {
+ typeParameters![i].buildOutlineExpressions(
+ libraryBuilder,
+ createBodyBuilderContext(),
+ classHierarchy,
+ computeTypeParameterScope(parentScope));
+ }
+ }
+
+ if (formals != null) {
+ // For const constructors we need to include default parameter values
+ // into the outline. For all other formals we need to call
+ // buildOutlineExpressions to clear initializerToken to prevent
+ // consuming too much memory.
+ for (FormalParameterBuilder formal in formals!) {
+ formal.buildOutlineExpressions(libraryBuilder, declarationBuilder,
+ buildDefaultValue: FormalParameterBuilder
+ .needsDefaultValuesBuiltAsOutlineExpressions(this));
+ }
+ }
+ hasBuiltOutlineExpressions = true;
+ }
+ if (isConst || _introductory.hasSuperInitializingFormals) {
+ // For modular compilation purposes we need to include initializers
+ // for const constructors into the outline.
+ LookupScope typeParameterScope =
+ computeTypeParameterScope(declarationBuilder.scope);
+ _buildConstructorForOutline(beginInitializers, typeParameterScope);
+ _introductory.buildBody();
+ }
+
+ addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
+ delayedDefaultValueCloners.addAll(_delayedDefaultValueCloners);
+ _delayedDefaultValueCloners.clear();
+
+ if (isConst && isAugmenting) {
+ _introductory.finishAugmentation(origin);
+ }
+
+ beginInitializers = null;
+ _hasBuiltOutlines = true;
+ }
@override
String get fullNameForErrors {
@@ -774,121 +747,6 @@
}
@override
- final int fileOffset;
-
- @override
- final Uri fileUri;
-
- @override
- final SourceLibraryBuilder libraryBuilder;
-
- @override
- final DeclarationBuilder declarationBuilder;
-
- DeclaredSourceConstructorBuilder(
- {required List<MetadataBuilder>? metadata,
- required Modifiers modifiers,
- required OmittedTypeBuilder returnType,
- required String name,
- required List<NominalParameterBuilder>? typeParameters,
- required this.formals,
- required this.libraryBuilder,
- required this.declarationBuilder,
- required this.fileUri,
- required int startOffset,
- required this.fileOffset,
- required int formalsOffset,
- required int endOffset,
- required Reference? constructorReference,
- required Reference? tearOffReference,
- required NameScheme nameScheme,
- String? nativeMethodName,
- required bool forAbstractClassOrEnumOrMixin,
- required Token? beginInitializers,
- bool isSynthetic = false})
- : _hasSuperInitializingFormals =
- formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
- _memberName = nameScheme.getDeclaredName(name),
- super(metadata, modifiers, returnType, name, typeParameters, formals,
- formalsOffset, nativeMethodName, beginInitializers) {
- _constructor = new Constructor(new FunctionNode(null),
- name: dummyName,
- fileUri: fileUri,
- reference: constructorReference,
- isSynthetic: isSynthetic)
- ..startFileOffset = startOffset
- ..fileOffset = fileOffset
- ..fileEndOffset = endOffset;
- nameScheme
- .getConstructorMemberName(name, isTearOff: false)
- .attachMember(_constructor);
- _constructorTearOff = createConstructorTearOffProcedure(
- nameScheme.getConstructorMemberName(name, isTearOff: true),
- libraryBuilder,
- fileUri,
- fileOffset,
- tearOffReference,
- forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin);
- }
-
- @override
- Builder get parent => declarationBuilder;
-
- @override
- bool get supportsTypeParameters => false;
-
- @override
- // Coverage-ignore(suite): Not run.
- Name get memberName => _memberName.name;
-
- @override
- SourceClassBuilder get classBuilder =>
- super.classBuilder as SourceClassBuilder;
-
- @override
- Member get readTarget =>
- _constructorTearOff ??
- // The case is need to ensure that the upper bound is [Member] and not
- // [GenericFunction].
- _constructor as Member;
-
- @override
- // Coverage-ignore(suite): Not run.
- Reference get readTargetReference =>
- (_constructorTearOff ?? _constructor).reference;
-
- @override
- // Coverage-ignore(suite): Not run.
- Member? get writeTarget => null;
-
- @override
- // Coverage-ignore(suite): Not run.
- Reference? get writeTargetReference => null;
-
- @override
- Member get invokeTarget => constructor;
-
- @override
- // Coverage-ignore(suite): Not run.
- Reference get invokeTargetReference => constructor.reference;
-
- @override
- FunctionNode get function => _constructor.function;
-
- @override
- // Coverage-ignore(suite): Not run.
- Iterable<Reference> get exportedMemberReferences => [constructor.reference];
-
- @override
- List<Initializer> get initializers => _constructor.initializers;
-
- @override
- DeclaredSourceConstructorBuilder get origin => actualOrigin ?? this;
-
- // Coverage-ignore(suite): Not run.
- List<SourceConstructorBuilder>? get augmentationsForTesting => _augmentations;
-
- @override
bool get isDeclarationInstanceMember => false;
@override
@@ -910,16 +768,6 @@
}
@override
- bool get isRedirecting {
- for (Initializer initializer in initializers) {
- if (initializer is RedirectingInitializer) {
- return true;
- }
- }
- return false;
- }
-
- @override
bool get isEffectivelyRedirecting {
bool isRedirecting = this.isRedirecting;
if (!isRedirecting) {
@@ -934,53 +782,21 @@
}
@override
- void buildOutlineNodes(BuildNodesCallback f) {
- _build();
- f(
- member: _constructor,
- tearOff: _constructorTearOff,
- kind: BuiltMemberKind.Constructor);
- }
-
- bool _hasBeenBuilt = false;
-
- void _build() {
- if (!_hasBeenBuilt) {
- buildFunction();
- _constructor.function.fileOffset = charOpenParenOffset;
- _constructor.function.fileEndOffset = _constructor.fileEndOffset;
- _constructor.function.typeParameters = const <TypeParameter>[];
- _constructor.isConst = isConst;
- _constructor.isExternal = isExternal;
-
- if (_constructorTearOff != null) {
- DelayedDefaultValueCloner delayedDefaultValueCloners =
- buildConstructorTearOffProcedure(
- tearOff: _constructorTearOff,
- declarationConstructor: constructor,
- implementationConstructor: _constructor,
- enclosingDeclarationTypeParameters:
- classBuilder.cls.typeParameters,
- libraryBuilder: libraryBuilder);
- _delayedDefaultValueCloners.add(delayedDefaultValueCloners);
- }
-
- _hasBeenBuilt = true;
- }
- _buildFormals(_constructor);
- }
-
- @override
VariableDeclaration getFormalParameter(int index) {
- if (parent is SourceEnumBuilder) {
+ if (declarationBuilder is SourceEnumBuilder) {
return formals![index + 2].variable!;
} else {
- return super.getFormalParameter(index);
+ return formals![index].variable!;
}
}
ConstructorBuilder? _computeSuperTargetBuilder(
List<Initializer>? initializers) {
+ if (declarationBuilder is! SourceClassBuilder) {
+ return null;
+ }
+ SourceClassBuilder classBuilder = declarationBuilder as SourceClassBuilder;
+
Member superTarget;
ClassBuilder superclassBuilder;
@@ -1031,14 +847,34 @@
}
}
- final bool _hasSuperInitializingFormals;
+ @override
+ void inferTypes(ClassHierarchyBase hierarchy) {
+ inferFormalTypes(hierarchy);
+ }
- final List<DelayedDefaultValueCloner> _delayedDefaultValueCloners =
- <DelayedDefaultValueCloner>[];
+ bool _hasFormalsInferred = false;
@override
+ void inferFormalTypes(ClassHierarchyBase hierarchy) {
+ if (_hasFormalsInferred) return;
+ if (formals != null) {
+ libraryBuilder.loader.withUriForCrashReporting(fileUri, fileOffset, () {
+ for (FormalParameterBuilder formal in formals!) {
+ if (formal.type is InferableTypeBuilder) {
+ if (formal.isInitializingFormal) {
+ formal.finalizeInitializingFormal(
+ declarationBuilder, this, hierarchy);
+ }
+ }
+ }
+ _inferSuperInitializingFormals(hierarchy);
+ });
+ }
+ _hasFormalsInferred = true;
+ }
+
void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {
- if (_hasSuperInitializingFormals) {
+ if (_introductory.hasSuperInitializingFormals) {
List<Initializer>? initializers;
if (beginInitializers != null) {
BodyBuilder bodyBuilder = libraryBuilder.loader
@@ -1050,17 +886,17 @@
initializers = bodyBuilder.parseInitializers(beginInitializers!,
doFinishConstructor: false);
}
- finalizeSuperInitializingFormals(
+ _finalizeSuperInitializingFormals(
hierarchy, _delayedDefaultValueCloners, initializers);
}
}
- void finalizeSuperInitializingFormals(
+ void _finalizeSuperInitializingFormals(
ClassHierarchyBase hierarchy,
List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
List<Initializer>? initializers) {
if (formals == null) return;
- if (!_hasSuperInitializingFormals) return;
+ if (!_introductory.hasSuperInitializingFormals) return;
void performRecoveryForErroneousCase() {
for (FormalParameterBuilder formal in formals!) {
@@ -1116,7 +952,7 @@
List<String>? namedSuperParameters;
Supertype? supertype = hierarchy.getClassAsInstanceOf(
- classBuilder.cls, superTarget.enclosingClass!);
+ classBuilder!.cls, superTarget.enclosingClass!);
assert(supertype != null);
Map<TypeParameter, DartType> substitution =
new Map<TypeParameter, DartType>.fromIterables(
@@ -1186,68 +1022,24 @@
}
if (positionalSuperParameters != null || namedSuperParameters != null) {
- if (!_hasDefaultValueCloner) {
- // If this constructor formals are part of a cyclic dependency this
- // might be called more than once.
- delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
- superTarget, constructor,
- positionalSuperParameters:
- positionalSuperParameters ?? const <int>[],
- namedSuperParameters: namedSuperParameters ?? const <String>[],
- isOutlineNode: true,
- libraryBuilder: libraryBuilder));
- if (_constructorTearOff != null) {
- delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
- superTarget, _constructorTearOff,
- positionalSuperParameters:
- positionalSuperParameters ?? const <int>[],
- namedSuperParameters: namedSuperParameters ?? const <String>[],
- isOutlineNode: true,
- libraryBuilder: libraryBuilder));
- }
- _hasDefaultValueCloner = true;
- }
+ _introductory.addSuperParameterDefaultValueCloners(
+ libraryBuilder: libraryBuilder,
+ delayedDefaultValueCloners: delayedDefaultValueCloners,
+ superTarget: superTarget,
+ positionalSuperParameters: positionalSuperParameters,
+ namedSuperParameters: namedSuperParameters);
}
}
- bool _hasBuiltOutlines = false;
-
- @override
- void buildOutlineExpressions(ClassHierarchy classHierarchy,
- List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
- if (_hasBuiltOutlines) return;
-
- formals?.infer(classHierarchy);
-
- if (isConst && isAugmenting) {
- origin.buildOutlineExpressions(
- classHierarchy, delayedDefaultValueCloners);
- }
- super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
-
- // For modular compilation purposes we need to include initializers
- // for const constructors into the outline. We also need to parse
- // initializers to infer types of the super-initializing parameters.
- if (isConst || _hasSuperInitializingFormals) {
- _buildConstructorForOutline(beginInitializers, classBuilder.scope);
- }
- addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
- if (isConst && isAugmenting) {
- _finishAugmentation();
- }
- beginInitializers = null;
- _hasBuiltOutlines = true;
- }
-
@override
void addSuperParameterDefaultValueCloners(
List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
- if (beginInitializers != null && constructor.initializers.isNotEmpty) {
+ if (beginInitializers != null && initializers.isNotEmpty) {
// If the initializers aren't built yet, we can't compute the super
// target. The synthetic initializers should be excluded, since they can
// be built separately from formal field initializers.
bool allInitializersAreSynthetic = true;
- for (Initializer initializer in constructor.initializers) {
+ for (Initializer initializer in initializers) {
if (!initializer.isSynthetic) {
allInitializersAreSynthetic = false;
break;
@@ -1255,160 +1047,17 @@
}
if (!allInitializersAreSynthetic) {
ConstructorBuilder? superTargetBuilder =
- _computeSuperTargetBuilder(constructor.initializers);
+ _computeSuperTargetBuilder(initializers);
if (superTargetBuilder is SourceConstructorBuilder) {
superTargetBuilder
.addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
}
}
}
-
- delayedDefaultValueCloners.addAll(_delayedDefaultValueCloners);
- _delayedDefaultValueCloners.clear();
}
- @override
- void buildFunction() {
- // According to the specification §9.3 the return type of a constructor
- // function is its enclosing class.
- super.buildFunction();
- Class enclosingClass = classBuilder.cls;
- List<DartType> typeParameterTypes = <DartType>[];
- for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
- TypeParameter typeParameter = enclosingClass.typeParameters[i];
- typeParameterTypes
- .add(new TypeParameterType.withDefaultNullability(typeParameter));
- }
- InterfaceType type = new InterfaceType(
- enclosingClass, Nullability.nonNullable, typeParameterTypes);
- returnType.registerInferredType(type);
- }
-
- Constructor get constructor =>
- isAugmenting ? origin.constructor : _constructor;
-
- void _finishAugmentation() {
- finishConstructorAugmentation(origin.constructor, _constructor);
-
- if (_constructorTearOff != null) {
- finishProcedureAugmentation(
- origin._constructorTearOff!, _constructorTearOff);
- }
- }
-
- @override
- int buildBodyNodes(BuildNodesCallback f) {
- if (!isAugmenting) return 0;
- _finishAugmentation();
- return 1;
- }
-
- @override
- void becomeNative(SourceLoader loader) {
- _constructor.isExternal = true;
- super.becomeNative(loader);
- }
-
- @override
- void applyAugmentation(Builder augmentation) {
- if (augmentation is DeclaredSourceConstructorBuilder) {
- if (checkAugmentation(
- augmentationLibraryBuilder: augmentation.libraryBuilder,
- origin: this,
- augmentation: augmentation)) {
- augmentation.actualOrigin = this;
- (_augmentations ??= []).add(augmentation);
- }
- } else {
- // Coverage-ignore-block(suite): Not run.
- reportAugmentationMismatch(
- originLibraryBuilder: libraryBuilder,
- origin: this,
- augmentation: augmentation);
- }
- }
-
- @override
- void prepareInitializers() {
- // For const constructors we parse initializers already at the outlining
- // stage, there is no easy way to make body building stage skip initializer
- // parsing, so we simply clear parsed initializers and rebuild them
- // again.
- // For when doing an experimental incremental compilation they are also
- // potentially done more than once (because it rebuilds the bodies of an old
- // 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 = [];
- redirectingInitializer = null;
- superInitializer = null;
- }
-
- @override
- void prependInitializer(Initializer initializer) {
- initializer.parent = constructor;
- constructor.initializers.insert(0, initializer);
- }
-
- @override
- void registerInitializedField(SourcePropertyBuilder fieldBuilder) {
- if (isAugmenting) {
- origin.registerInitializedField(fieldBuilder);
- } else {
- (_initializedFields ??= {}).add(fieldBuilder);
- }
- }
-
- @override
- Set<SourcePropertyBuilder>? takeInitializedFields() {
- Set<SourcePropertyBuilder>? result = _initializedFields;
- _initializedFields = null;
- return result;
- }
-
- void ensureGrowableFormals() {
- if (formals != null) {
- formals = new List<FormalParameterBuilder>.of(formals!, growable: true);
- } else {
- formals = <FormalParameterBuilder>[];
- }
- }
-
- @override
- void checkTypes(SourceLibraryBuilder library, NameSpace nameSpace,
- TypeEnvironment typeEnvironment) {
- super.checkTypes(library, nameSpace, typeEnvironment);
- List<DeclaredSourceConstructorBuilder>? augmentations = _augmentations;
- if (augmentations != null) {
- for (DeclaredSourceConstructorBuilder augmentation in augmentations) {
- augmentation.checkTypes(library, nameSpace, typeEnvironment);
- }
- }
- }
-
- @override
- DartType substituteFieldType(DartType fieldType) {
- // Nothing to do. Regular generative constructors don't have their own
- // type parameters.
- return fieldType;
- }
-
- @override
BodyBuilderContext createBodyBuilderContext() {
- return new ConstructorBodyBuilderContext(this, constructor);
- }
-
- // TODO(johnniwinther): Add annotations to tear-offs.
- @override
- Iterable<Annotatable> get annotatables => [constructor];
-
- @override
- bool get isAugmented {
- if (isAugmenting) {
- return origin._augmentations!.last != this;
- } else {
- return _augmentations != null;
- }
+ return new ConstructorBodyBuilderContext(this, invokeTarget);
}
}
@@ -1652,322 +1301,6 @@
TypeEnvironment typeEnvironment) {}
}
-class SourceExtensionTypeConstructorBuilder
- extends AbstractSourceConstructorBuilder {
- @override
- final SourceLibraryBuilder libraryBuilder;
-
- @override
- final SourceExtensionTypeDeclarationBuilder declarationBuilder;
-
- late final Procedure _constructor;
-
- @override
- late final Procedure? _constructorTearOff;
-
- Set<SourcePropertyBuilder>? _initializedFields;
-
- @override
- List<Initializer> initializers = [];
-
- final MemberName _memberName;
-
- DelayedDefaultValueCloner? _delayedDefaultValueCloner;
-
- @override
- final int fileOffset;
-
- @override
- final Uri fileUri;
-
- SourceExtensionTypeConstructorBuilder(
- {required List<MetadataBuilder>? metadata,
- required Modifiers modifiers,
- required OmittedTypeBuilder returnType,
- required String name,
- required List<NominalParameterBuilder>? typeParameters,
- required List<FormalParameterBuilder>? formals,
- required this.libraryBuilder,
- required this.declarationBuilder,
- required this.fileUri,
- required int startOffset,
- required this.fileOffset,
- required int formalsOffset,
- required int endOffset,
- required Reference? constructorReference,
- required Reference? tearOffReference,
- required NameScheme nameScheme,
- String? nativeMethodName,
- required bool forAbstractClassOrEnumOrMixin,
- required Token? beginInitializers})
- : _memberName = nameScheme.getDeclaredName(name),
- super(metadata, modifiers, returnType, name, typeParameters, formals,
- formalsOffset, nativeMethodName, beginInitializers) {
- _constructor = new Procedure(
- dummyName, ProcedureKind.Method, new FunctionNode(null),
- fileUri: fileUri, reference: constructorReference)
- ..fileOffset = fileOffset
- ..fileEndOffset = endOffset;
- nameScheme
- .getConstructorMemberName(name, isTearOff: false)
- .attachMember(_constructor);
- _constructorTearOff = createConstructorTearOffProcedure(
- nameScheme.getConstructorMemberName(name, isTearOff: true),
- libraryBuilder,
- fileUri,
- fileOffset,
- tearOffReference,
- forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin,
- forceCreateLowering: true)
- ?..isExtensionTypeMember = true;
- }
-
- @override
- Builder get parent => declarationBuilder;
-
- @override
- // Coverage-ignore(suite): Not run.
- Name get memberName => _memberName.name;
-
- @override
- Member get readTarget =>
- _constructorTearOff ?? // Coverage-ignore(suite): Not run.
- _constructor;
-
- @override
- // Coverage-ignore(suite): Not run.
- Reference get readTargetReference =>
- (_constructorTearOff ?? _constructor).reference;
-
- @override
- // Coverage-ignore(suite): Not run.
- Member? get writeTarget => null;
-
- @override
- // Coverage-ignore(suite): Not run.
- Reference? get writeTargetReference => null;
-
- @override
- Member get invokeTarget => _constructor;
-
- @override
- // Coverage-ignore(suite): Not run.
- Reference get invokeTargetReference => _constructor.reference;
-
- @override
- FunctionNode get function => _constructor.function;
-
- @override
- // Coverage-ignore(suite): Not run.
- Iterable<Reference> get exportedMemberReferences => [_constructor.reference];
-
- @override
- // Coverage-ignore(suite): Not run.
- void addSuperParameterDefaultValueCloners(
- List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {}
-
- @override
- void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {
- if (formals != null) {
- for (FormalParameterBuilder formal in formals!) {
- if (formal.isSuperInitializingFormal) {
- TypeBuilder formalTypeBuilder = formal.type;
- if (formalTypeBuilder is InferableTypeBuilder) {
- formalTypeBuilder.registerType(const InvalidType());
- }
- }
- }
- }
- }
-
- @override
- void buildOutlineExpressions(ClassHierarchy classHierarchy,
- List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
- super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
-
- if (isConst) {
- // For modular compilation purposes we need to include initializers
- // for const constructors into the outline.
- LookupScope typeParameterScope =
- computeTypeParameterScope(declarationBuilder.scope);
- _buildConstructorForOutline(beginInitializers, typeParameterScope);
- _buildBody();
- }
- beginInitializers = null;
-
- if (_delayedDefaultValueCloner != null) {
- delayedDefaultValueCloners.add(_delayedDefaultValueCloner!);
- }
- }
-
- bool _hasBuiltBody = false;
-
- void _buildBody() {
- if (_hasBuiltBody) {
- return;
- }
- if (!isExternal) {
- VariableDeclaration thisVariable = this.thisVariable!;
- List<Statement> statements = [thisVariable];
- ExtensionTypeInitializerToStatementConverter visitor =
- new ExtensionTypeInitializerToStatementConverter(
- statements, thisVariable);
- for (Initializer initializer in initializers) {
- initializer.accept(visitor);
- }
- if (body != null && body is! EmptyStatement) {
- statements.add(body!);
- }
- statements.add(new ReturnStatement(new VariableGet(thisVariable)));
- body = new Block(statements);
- }
- _hasBuiltBody = true;
- }
-
- @override
- int buildBodyNodes(BuildNodesCallback f) {
- _buildBody();
- // TODO(johnniwinther): Support augmentation.
- return 0;
- }
-
- @override
- void buildOutlineNodes(BuildNodesCallback f) {
- _build();
- f(
- member: _constructor,
- tearOff: _constructorTearOff,
- kind: BuiltMemberKind.ExtensionTypeConstructor);
- }
-
- bool _hasBeenBuilt = false;
-
- @override
- void buildFunction() {
- // According to the specification §9.3 the return type of a constructor
- // function is its enclosing class.
- super.buildFunction();
- ExtensionTypeDeclaration extensionTypeDeclaration =
- declarationBuilder.extensionTypeDeclaration;
- List<DartType> typeParameterTypes = <DartType>[];
- for (int i = 0; i < function.typeParameters.length; i++) {
- TypeParameter typeParameter = function.typeParameters[i];
- typeParameterTypes
- .add(new TypeParameterType.withDefaultNullability(typeParameter));
- }
- ExtensionType type = new ExtensionType(
- extensionTypeDeclaration, Nullability.nonNullable, typeParameterTypes);
- returnType.registerInferredType(type);
- }
-
- void _build() {
- if (!_hasBeenBuilt) {
- buildFunction();
- _constructor.function.fileOffset = charOpenParenOffset;
- _constructor.function.fileEndOffset = _constructor.fileEndOffset;
- _constructor.isConst = isConst;
- _constructor.isExternal = isExternal;
- _constructor.isStatic = true;
- _constructor.isExtensionTypeMember = true;
-
- if (_constructorTearOff != null) {
- _delayedDefaultValueCloner = buildConstructorTearOffProcedure(
- tearOff: _constructorTearOff,
- declarationConstructor: _constructor,
- implementationConstructor: _constructor,
- libraryBuilder: libraryBuilder);
- }
-
- _hasBeenBuilt = true;
- }
- _buildFormals(_constructor);
- }
-
- @override
- void prepareInitializers() {
- // For const constructors we parse initializers already at the outlining
- // stage, there is no easy way to make body building stage skip initializer
- // parsing, so we simply clear parsed initializers and rebuild them
- // again.
- // For when doing an experimental incremental compilation they are also
- // potentially done more than once (because it rebuilds the bodies of an old
- // 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 = [];
- redirectingInitializer = null;
- superInitializer = null;
- }
-
- @override
- void prependInitializer(Initializer initializer) {
- initializers.insert(0, initializer);
- }
-
- @override
- void registerInitializedField(SourcePropertyBuilder fieldBuilder) {
- (_initializedFields ??= {}).add(fieldBuilder);
- }
-
- @override
- Set<SourcePropertyBuilder>? takeInitializedFields() {
- Set<SourcePropertyBuilder>? result = _initializedFields;
- _initializedFields = null;
- return result;
- }
-
- @override
- bool get isEffectivelyExternal => isExternal;
-
- @override
- bool get isRedirecting {
- for (Initializer initializer in initializers) {
- if (initializer is ExtensionTypeRedirectingInitializer) {
- return true;
- }
- }
- return false;
- }
-
- @override
- bool get isEffectivelyRedirecting => isRedirecting;
-
- Substitution? _substitutionCache;
-
- Substitution get _substitution {
- if (typeParameters != null) {
- assert(
- declarationBuilder.typeParameters!.length == typeParameters?.length);
- _substitutionCache = Substitution.fromPairs(
- declarationBuilder.extensionTypeDeclaration.typeParameters,
- new List<DartType>.generate(
- declarationBuilder.typeParameters!.length,
- (int index) => new TypeParameterType.withDefaultNullability(
- function.typeParameters[index])));
- } else {
- _substitutionCache = Substitution.empty;
- }
- return _substitutionCache!;
- }
-
- @override
- DartType substituteFieldType(DartType fieldType) {
- return _substitution.substituteType(fieldType);
- }
-
- @override
- BodyBuilderContext createBodyBuilderContext() {
- return new ExtensionTypeConstructorBodyBuilderContext(this, _constructor);
- }
-
- // TODO(johnniwinther): Add annotations to tear-offs.
- @override
- Iterable<Annotatable> get annotatables => [_constructor];
-
- @override
- bool get isAugmented => false;
-}
-
class ExtensionTypeInitializerToStatementConverter
implements InitializerVisitor<void> {
VariableDeclaration thisVariable;
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index daf4e30..ed2fe0e 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -33,6 +33,7 @@
messageNoUnnamedConstructorInObject,
noLength,
templateEnumContainsRestrictedInstanceDeclaration;
+import '../fragment/constructor/declaration.dart';
import '../fragment/fragment.dart';
import '../kernel/body_builder_context.dart';
import '../kernel/constructor_tearoff_lowering.dart';
@@ -58,17 +59,13 @@
final TypeBuilder _underscoreEnumTypeBuilder;
- late final NamedTypeBuilder intType;
-
- late final NamedTypeBuilder stringType;
-
late final NamedTypeBuilder objectType;
late final NamedTypeBuilder listType;
late final NamedTypeBuilder selfType;
- DeclaredSourceConstructorBuilder? synthesizedDefaultConstructorBuilder;
+ SourceConstructorBuilderImpl? synthesizedDefaultConstructorBuilder;
late final _EnumValuesFieldDeclaration _enumValuesFieldDeclaration;
@@ -141,30 +138,6 @@
super.buildScopes(coreLibrary);
_createSynthesizedMembers(coreLibrary);
- // Include duplicates to install the formals on all constructors to avoid a
- // crash later.
- Iterator<MemberBuilder> iterator =
- nameSpace.filteredConstructorNameIterator(
- includeDuplicates: true, includeAugmentations: true);
- while (iterator.moveNext()) {
- MemberBuilder member = iterator.current;
- if (member is DeclaredSourceConstructorBuilder) {
- member.ensureGrowableFormals();
-
- FormalParameterBuilder nameFormalParameterBuilder =
- new FormalParameterBuilder(FormalParameterKind.requiredPositional,
- Modifiers.empty, stringType, "#name", fileOffset,
- fileUri: fileUri, hasImmediatelyDeclaredInitializer: false);
- member.formals!.insert(0, nameFormalParameterBuilder);
-
- FormalParameterBuilder indexFormalParameterBuilder =
- new FormalParameterBuilder(FormalParameterKind.requiredPositional,
- Modifiers.empty, intType, "#index", fileOffset,
- fileUri: fileUri, hasImmediatelyDeclaredInitializer: false);
- member.formals!.insert(0, indexFormalParameterBuilder);
- }
- }
-
Iterator<MemberBuilder> constructorIterator =
nameSpace.filteredConstructorIterator(
includeDuplicates: false, includeAugmentations: true);
@@ -180,23 +153,6 @@
void _createSynthesizedMembers(LibraryBuilder coreLibrary) {
// TODO(ahe): These types shouldn't be looked up in scope, they come
// directly from dart:core.
- intType = new NamedTypeBuilderImpl(
- const PredefinedTypeName("int"), const NullabilityBuilder.omitted(),
- instanceTypeParameterAccess:
- // If "int" resolves to an instance type parameter then that we
- // would allowed (the types that we are adding are in instance
- // context after all) but it would be unexpected and we would like
- // an assertion failure, since "int" was meant to be `int` from
- // `dart:core`.
- // TODO(johnniwinther): Add a more robust way of creating named
- // typed builders for dart:core types. This might be needed for the
- // enhanced enums feature where enums can actually declare type
- // variables.
- InstanceTypeParameterAccessState.Unexpected);
- stringType = new NamedTypeBuilderImpl(
- const PredefinedTypeName("String"), const NullabilityBuilder.omitted(),
- instanceTypeParameterAccess:
- InstanceTypeParameterAccessState.Unexpected);
objectType = new NamedTypeBuilderImpl(
const PredefinedTypeName("Object"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess:
@@ -326,35 +282,55 @@
}
}
if (needsSynthesizedDefaultConstructor) {
- synthesizedDefaultConstructorBuilder =
- new DeclaredSourceConstructorBuilder(
- metadata: null,
- modifiers: Modifiers.Const,
+ FormalParameterBuilder nameFormalParameterBuilder =
+ new FormalParameterBuilder(
+ FormalParameterKind.requiredPositional,
+ Modifiers.empty,
+ libraryBuilder.loader.target.stringType,
+ "#name",
+ fileOffset,
+ fileUri: fileUri,
+ hasImmediatelyDeclaredInitializer: false);
+
+ FormalParameterBuilder indexFormalParameterBuilder =
+ new FormalParameterBuilder(
+ FormalParameterKind.requiredPositional,
+ Modifiers.empty,
+ libraryBuilder.loader.target.intType,
+ "#index",
+ fileOffset,
+ fileUri: fileUri,
+ hasImmediatelyDeclaredInitializer: false);
+
+ ConstructorDeclaration constructorDeclaration =
+ new DefaultEnumConstructorDeclaration(
returnType:
libraryBuilder.loader.inferableTypes.addInferableType(),
- name: "",
- typeParameters: null,
- formals: [],
- libraryBuilder: libraryBuilder,
- declarationBuilder: this,
+ formals: [
+ indexFormalParameterBuilder,
+ nameFormalParameterBuilder
+ ],
fileUri: fileUri,
- startOffset: fileOffset,
- fileOffset: fileOffset,
- formalsOffset: fileOffset,
- endOffset: endOffset,
- constructorReference: constructorReference,
- tearOffReference: tearOffReference,
- nameScheme: new NameScheme(
- isInstanceMember: false,
- containerName: new ClassName(name),
- containerType: ContainerType.Class,
- libraryName: libraryName),
- forAbstractClassOrEnumOrMixin: true,
- isSynthetic: true,
- // Trick the constructor to be built during the outline phase.
- // TODO(johnniwinther): Avoid relying on [beginInitializers] to
- // ensure building constructors creation during the outline phase.
- beginInitializers: new Token.eof(-1));
+ fileOffset: fileOffset);
+ synthesizedDefaultConstructorBuilder = new SourceConstructorBuilderImpl(
+ modifiers: Modifiers.Const,
+ name: "",
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: this,
+ fileUri: fileUri,
+ fileOffset: fileOffset,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: new NameScheme(
+ isInstanceMember: false,
+ containerName: new ClassName(name),
+ containerType: ContainerType.Class,
+ libraryName: libraryName),
+ // Trick the constructor to be built during the outline phase.
+ // TODO(johnniwinther): Avoid relying on [beginInitializers] to
+ // ensure building constructors creation during the outline phase.
+ beginInitializers: new Token.eof(-1),
+ constructorDeclaration: constructorDeclaration);
synthesizedDefaultConstructorBuilder!
.registerInitializedField(valuesBuilder);
nameSpace.addConstructor("", synthesizedDefaultConstructorBuilder!);
@@ -379,7 +355,9 @@
isAbstract: false,
reference: toStringReference,
creator: new _EnumToStringCreator(
- this, stringType, _underscoreEnumTypeBuilder));
+ this,
+ libraryBuilder.loader.target.stringType,
+ _underscoreEnumTypeBuilder));
nameSpace.addLocalMember(toStringBuilder.name, toStringBuilder,
setter: false);
nameSpaceBuilder.checkTypeParameterConflict(libraryBuilder,
@@ -410,9 +388,6 @@
}
}
- intType.resolveIn(coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
- stringType.resolveIn(
- coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
objectType.resolveIn(
coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
listType.resolveIn(coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
@@ -429,7 +404,7 @@
if (identical(this.supertypeBuilder, _underscoreEnumTypeBuilder)) {
if (synthesizedDefaultConstructorBuilder != null) {
Constructor constructor =
- synthesizedDefaultConstructorBuilder!.constructor;
+ synthesizedDefaultConstructorBuilder!.invokeTarget as Constructor;
ClassBuilder objectClass = objectType.declaration as ClassBuilder;
ClassBuilder enumClass =
_underscoreEnumTypeBuilder.declaration as ClassBuilder;
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
index fedd303..830bc84 100644
--- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -860,14 +860,14 @@
/// Looks up the constructor by [name] on the class built by this class
/// builder.
- SourceExtensionTypeConstructorBuilder? lookupConstructor(Name name) {
+ SourceConstructorBuilderImpl? lookupConstructor(Name name) {
if (name.text == "new") {
// Coverage-ignore-block(suite): Not run.
name = new Name("", name.library);
}
Builder? builder = nameSpace.lookupConstructor(name.text);
- if (builder is SourceExtensionTypeConstructorBuilder) {
+ if (builder is SourceConstructorBuilderImpl) {
return builder;
}
return null;
diff --git a/pkg/front_end/lib/src/source/source_factory_builder.dart b/pkg/front_end/lib/src/source/source_factory_builder.dart
index b516aac..cd560ec 100644
--- a/pkg/front_end/lib/src/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/source/source_factory_builder.dart
@@ -515,7 +515,7 @@
}
@override
- void setBody(Statement body) {
+ void registerFunctionBody(Statement body) {
_member.setBody(body);
}
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index ff69493..941edfc 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/reference_from_index.dart';
@@ -12,12 +13,14 @@
import '../base/scope.dart';
import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
+import '../builder/formal_parameter_builder.dart';
import '../builder/function_builder.dart';
import '../builder/member_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/prefix_builder.dart';
import '../builder/type_builder.dart';
+import '../fragment/constructor/declaration.dart';
import '../fragment/fragment.dart';
import 'builder_factory.dart';
import 'name_scheme.dart';
@@ -1583,11 +1586,32 @@
methodBuilder;
}
case ConstructorFragment():
- List<NominalParameterBuilder>? typeParameters =
- fragment.typeParameters?.builders;
+ String name = fragment.name;
+ NameScheme nameScheme = new NameScheme(
+ isInstanceMember: false,
+ containerName: containerName,
+ containerType: containerType,
+ libraryName: indexedLibrary != null
+ ? new LibraryName(indexedLibrary.library.reference)
+ : enclosingLibraryBuilder.libraryName);
+
+ Reference? constructorReference;
+ Reference? tearOffReference;
+
+ if (indexedContainer != null) {
+ constructorReference = indexedContainer!.lookupConstructorReference(
+ nameScheme.getConstructorMemberName(name, isTearOff: false).name);
+ tearOffReference = indexedContainer!.lookupGetterReference(
+ nameScheme.getConstructorMemberName(name, isTearOff: true).name);
+ }
+
+ SourceConstructorBuilderImpl constructorBuilder;
switch (declarationBuilder!) {
- case ExtensionBuilder():
case ExtensionTypeDeclarationBuilder():
+ List<NominalParameterBuilder>? typeParameters = fragment
+ .typeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
NominalParameterCopy? nominalVariableCopy =
NominalParameterCopy.copyTypeParameters(
unboundNominalParameters, declarationBuilder.typeParameters,
@@ -1603,74 +1627,109 @@
typeParameters = nominalVariableCopy.newParameterBuilders;
}
}
+ fragment.typeParameterNameSpace.addTypeParameters(
+ problemReporting, typeParameters,
+ ownerName: fragment.name, allowNameConflict: true);
+ ConstructorDeclaration constructorDeclaration =
+ new ExtensionTypeConstructorDeclaration(fragment,
+ typeParameters: typeParameters);
+ constructorBuilder = new SourceConstructorBuilderImpl(
+ modifiers: fragment.modifiers,
+ name: name,
+ libraryBuilder: enclosingLibraryBuilder,
+ declarationBuilder:
+ declarationBuilder as SourceExtensionTypeDeclarationBuilder,
+ fileUri: fragment.fileUri,
+ fileOffset: fragment.fullNameOffset,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: nameScheme,
+ nativeMethodName: fragment.nativeMethodName,
+ beginInitializers: fragment.beginInitializers,
+ constructorDeclaration: constructorDeclaration);
case ClassBuilder():
- }
- fragment.typeParameterNameSpace.addTypeParameters(
- problemReporting, typeParameters,
- ownerName: fragment.name, allowNameConflict: true);
-
- String name = fragment.name;
- NameScheme nameScheme = new NameScheme(
- isInstanceMember: false,
- containerName: containerName,
- containerType: containerType,
- libraryName: indexedLibrary != null
- ? new LibraryName(indexedLibrary.library.reference)
- : enclosingLibraryBuilder.libraryName);
-
- Reference? constructorReference;
- Reference? tearOffReference;
-
- if (indexedContainer != null) {
- constructorReference = indexedContainer!.lookupConstructorReference(
- nameScheme.getConstructorMemberName(name, isTearOff: false).name);
- tearOffReference = indexedContainer!.lookupGetterReference(
- nameScheme.getConstructorMemberName(name, isTearOff: true).name);
- }
-
- AbstractSourceConstructorBuilder constructorBuilder;
- if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
- constructorBuilder = new SourceExtensionTypeConstructorBuilder(
- metadata: fragment.metadata,
- modifiers: fragment.modifiers,
- returnType: fragment.returnType,
- name: name,
- typeParameters: typeParameters,
- formals: fragment.formals,
- libraryBuilder: enclosingLibraryBuilder,
- declarationBuilder: declarationBuilder,
- fileUri: fragment.fileUri,
- startOffset: fragment.startOffset,
- fileOffset: fragment.fullNameOffset,
- formalsOffset: fragment.formalsOffset,
- endOffset: fragment.endOffset,
- constructorReference: constructorReference,
- tearOffReference: tearOffReference,
- nameScheme: nameScheme,
- nativeMethodName: fragment.nativeMethodName,
- forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
- beginInitializers: fragment.beginInitializers);
- } else {
- constructorBuilder = new DeclaredSourceConstructorBuilder(
- metadata: fragment.metadata,
- modifiers: fragment.modifiers,
- returnType: fragment.returnType,
- name: fragment.name,
- typeParameters: typeParameters,
- formals: fragment.formals,
- libraryBuilder: enclosingLibraryBuilder,
- declarationBuilder: declarationBuilder,
- fileUri: fragment.fileUri,
- startOffset: fragment.startOffset,
- fileOffset: fragment.fullNameOffset,
- formalsOffset: fragment.formalsOffset,
- endOffset: fragment.endOffset,
- constructorReference: constructorReference,
- tearOffReference: tearOffReference,
- nameScheme: nameScheme,
- nativeMethodName: fragment.nativeMethodName,
- forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
- beginInitializers: fragment.beginInitializers);
+ List<FormalParameterBuilder>? syntheticFormals;
+ if (declarationBuilder.isEnum) {
+ syntheticFormals = [
+ new FormalParameterBuilder(
+ FormalParameterKind.requiredPositional,
+ Modifiers.empty,
+ loader.target.intType,
+ "#index",
+ fragment.fullNameOffset,
+ fileUri: fragment.fileUri,
+ hasImmediatelyDeclaredInitializer: false),
+ new FormalParameterBuilder(
+ FormalParameterKind.requiredPositional,
+ Modifiers.empty,
+ loader.target.stringType,
+ "#name",
+ fragment.fullNameOffset,
+ fileUri: fragment.fileUri,
+ hasImmediatelyDeclaredInitializer: false),
+ ];
+ }
+ List<NominalParameterBuilder>? typeParameters =
+ fragment.typeParameters?.builders;
+ fragment.typeParameterNameSpace.addTypeParameters(
+ problemReporting, typeParameters,
+ ownerName: fragment.name, allowNameConflict: true);
+ ConstructorDeclaration constructorDeclaration =
+ new RegularConstructorDeclaration(fragment,
+ typeParameters: typeParameters,
+ syntheticFormals: syntheticFormals);
+ constructorBuilder = new SourceConstructorBuilderImpl(
+ modifiers: fragment.modifiers,
+ name: fragment.name,
+ libraryBuilder: enclosingLibraryBuilder,
+ declarationBuilder: declarationBuilder,
+ fileUri: fragment.fileUri,
+ fileOffset: fragment.fullNameOffset,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: nameScheme,
+ nativeMethodName: fragment.nativeMethodName,
+ beginInitializers: fragment.beginInitializers,
+ constructorDeclaration: constructorDeclaration);
+ case ExtensionBuilder():
+ List<NominalParameterBuilder>? typeParameters = fragment
+ .typeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+ NominalParameterCopy? nominalVariableCopy =
+ NominalParameterCopy.copyTypeParameters(
+ unboundNominalParameters, declarationBuilder.typeParameters,
+ kind: TypeParameterKind.extensionSynthesized,
+ instanceTypeParameterAccess:
+ InstanceTypeParameterAccessState.Allowed);
+ if (nominalVariableCopy != null) {
+ if (typeParameters != null) {
+ // Coverage-ignore-block(suite): Not run.
+ typeParameters = nominalVariableCopy.newParameterBuilders
+ ..addAll(typeParameters);
+ } else {
+ typeParameters = nominalVariableCopy.newParameterBuilders;
+ }
+ }
+ fragment.typeParameterNameSpace.addTypeParameters(
+ problemReporting, typeParameters,
+ ownerName: fragment.name, allowNameConflict: true);
+ ConstructorDeclaration constructorDeclaration =
+ new RegularConstructorDeclaration(fragment,
+ typeParameters: typeParameters, syntheticFormals: null);
+ constructorBuilder = new SourceConstructorBuilderImpl(
+ modifiers: fragment.modifiers,
+ name: fragment.name,
+ libraryBuilder: enclosingLibraryBuilder,
+ declarationBuilder: declarationBuilder,
+ fileUri: fragment.fileUri,
+ fileOffset: fragment.fullNameOffset,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: nameScheme,
+ nativeMethodName: fragment.nativeMethodName,
+ beginInitializers: fragment.beginInitializers,
+ constructorDeclaration: constructorDeclaration);
}
fragment.builder = constructorBuilder;
builders.add(new _AddBuilder(fragment.name, constructorBuilder,
@@ -1685,19 +1744,6 @@
case PrimaryConstructorFragment():
String name = fragment.name;
- NominalParameterCopy? nominalVariableCopy =
- NominalParameterCopy.copyTypeParameters(
- unboundNominalParameters, declarationBuilder!.typeParameters,
- kind: TypeParameterKind.extensionSynthesized,
- instanceTypeParameterAccess:
- InstanceTypeParameterAccessState.Allowed);
-
- List<NominalParameterBuilder>? typeParameters =
- nominalVariableCopy?.newParameterBuilders;
- fragment.typeParameterNameSpace.addTypeParameters(
- problemReporting, typeParameters,
- ownerName: fragment.name, allowNameConflict: true);
-
NameScheme nameScheme = new NameScheme(
isInstanceMember: false,
containerName: containerName,
@@ -1716,50 +1762,57 @@
nameScheme.getConstructorMemberName(name, isTearOff: true).name);
}
- AbstractSourceConstructorBuilder constructorBuilder;
- if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
- constructorBuilder = new SourceExtensionTypeConstructorBuilder(
- metadata: null,
- modifiers: fragment.modifiers,
- returnType: fragment.returnType,
- name: name,
- typeParameters: typeParameters,
- formals: fragment.formals,
- libraryBuilder: enclosingLibraryBuilder,
- declarationBuilder: declarationBuilder,
- fileUri: fragment.fileUri,
- startOffset: fragment.startOffset,
- fileOffset: fragment.fileOffset,
- formalsOffset: fragment.formalsOffset,
- // TODO(johnniwinther): Provide `endOffset`.
- endOffset: fragment.formalsOffset,
- constructorReference: constructorReference,
- tearOffReference: tearOffReference,
- nameScheme: nameScheme,
- forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
- beginInitializers: fragment.beginInitializers);
- } else {
- // Coverage-ignore-block(suite): Not run.
- constructorBuilder = new DeclaredSourceConstructorBuilder(
- metadata: null,
- modifiers: fragment.modifiers,
- returnType: fragment.returnType,
- name: fragment.name,
- typeParameters: typeParameters,
- formals: fragment.formals,
- libraryBuilder: enclosingLibraryBuilder,
- declarationBuilder: declarationBuilder,
- fileUri: fragment.fileUri,
- startOffset: fragment.startOffset,
- fileOffset: fragment.fileOffset,
- formalsOffset: fragment.formalsOffset,
- // TODO(johnniwinther): Provide `endOffset`.
- endOffset: fragment.formalsOffset,
- constructorReference: constructorReference,
- tearOffReference: tearOffReference,
- nameScheme: nameScheme,
- forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
- beginInitializers: fragment.beginInitializers);
+ SourceConstructorBuilderImpl constructorBuilder;
+ switch (declarationBuilder!) {
+ case ExtensionTypeDeclarationBuilder():
+ NominalParameterCopy? nominalVariableCopy =
+ NominalParameterCopy.copyTypeParameters(
+ unboundNominalParameters, declarationBuilder.typeParameters,
+ kind: TypeParameterKind.extensionSynthesized,
+ instanceTypeParameterAccess:
+ InstanceTypeParameterAccessState.Allowed);
+
+ List<NominalParameterBuilder>? typeParameters =
+ nominalVariableCopy?.newParameterBuilders;
+ fragment.typeParameterNameSpace.addTypeParameters(
+ problemReporting, typeParameters,
+ ownerName: fragment.name, allowNameConflict: true);
+ ConstructorDeclaration constructorDeclaration =
+ new ExtensionTypePrimaryConstructorDeclaration(fragment,
+ typeParameters: typeParameters);
+ constructorBuilder = new SourceConstructorBuilderImpl(
+ modifiers: fragment.modifiers,
+ name: name,
+ libraryBuilder: enclosingLibraryBuilder,
+ declarationBuilder:
+ declarationBuilder as SourceExtensionTypeDeclarationBuilder,
+ fileUri: fragment.fileUri,
+ fileOffset: fragment.fileOffset,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: nameScheme,
+ beginInitializers: fragment.beginInitializers,
+ constructorDeclaration: constructorDeclaration);
+ // Coverage-ignore(suite): Not run.
+ case ClassBuilder():
+ ConstructorDeclaration constructorDeclaration =
+ new PrimaryConstructorDeclaration(fragment);
+ constructorBuilder = new SourceConstructorBuilderImpl(
+ modifiers: fragment.modifiers,
+ name: fragment.name,
+ libraryBuilder: enclosingLibraryBuilder,
+ declarationBuilder: declarationBuilder,
+ fileUri: fragment.fileUri,
+ fileOffset: fragment.fileOffset,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: nameScheme,
+ beginInitializers: fragment.beginInitializers,
+ constructorDeclaration: constructorDeclaration);
+ // Coverage-ignore(suite): Not run.
+ case ExtensionBuilder():
+ throw new UnsupportedError(
+ 'Unexpected extension primary constructor $fragment');
}
fragment.builder = constructorBuilder;
builders.add(new _AddBuilder(fragment.name, constructorBuilder,
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
index 8dfb41e..cd32bfa 100644
--- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
@@ -151,7 +151,7 @@
@override
final TypeAnalyzerOptions options;
- final ConstructorDeclaration? constructorDeclaration;
+ final ConstructorDeclarationBuilder? constructorDeclaration;
@override
late final SharedTypeAnalyzerErrors errors = new SharedTypeAnalyzerErrors(
diff --git a/pkg/front_end/lib/src/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/type_inference/type_inferrer.dart
index 426df7b..8730c11 100644
--- a/pkg/front_end/lib/src/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/type_inference/type_inferrer.dart
@@ -52,8 +52,10 @@
DartType returnType, AsyncMarker asyncMarker, Statement body);
/// Performs type inference on the given constructor initializer.
- InitializerInferenceResult inferInitializer(InferenceHelper helper,
- ConstructorDeclaration constructorDeclaration, Initializer initializer);
+ InitializerInferenceResult inferInitializer(
+ InferenceHelper helper,
+ ConstructorDeclarationBuilder constructorDeclaration,
+ Initializer initializer);
/// Performs type inference on the given metadata annotations.
void inferMetadata(
@@ -141,7 +143,7 @@
typeCacheLegacy: engine.typeCacheLegacy);
InferenceVisitorBase _createInferenceVisitor(InferenceHelper helper,
- [ConstructorDeclaration? constructorDeclaration]) {
+ [ConstructorDeclarationBuilder? constructorDeclaration]) {
// For full (non-top level) inference, we need access to the
// InferenceHelper so that we can perform error reporting.
return new InferenceVisitorImpl(
@@ -246,8 +248,10 @@
}
@override
- InitializerInferenceResult inferInitializer(InferenceHelper helper,
- ConstructorDeclaration constructorDeclaration, Initializer initializer) {
+ InitializerInferenceResult inferInitializer(
+ InferenceHelper helper,
+ ConstructorDeclarationBuilder constructorDeclaration,
+ Initializer initializer) {
// Use polymorphic dispatch on [KernelInitializer] to perform whatever
// kind of type inference is correct for this kind of initializer.
// TODO(paulberry): experiment to see if dynamic dispatch would be better,
@@ -349,8 +353,10 @@
}
@override
- InitializerInferenceResult inferInitializer(InferenceHelper helper,
- ConstructorDeclaration constructorDeclaration, Initializer initializer) {
+ InitializerInferenceResult inferInitializer(
+ InferenceHelper helper,
+ ConstructorDeclarationBuilder constructorDeclaration,
+ Initializer initializer) {
benchmarker.beginSubdivide(BenchmarkSubdivides.inferInitializer);
InitializerInferenceResult result =
impl.inferInitializer(helper, constructorDeclaration, initializer);
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 438e04e..89d9b71 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -479,6 +479,16 @@
missCount: 0,
),
// 100.0%.
+ "package:front_end/src/fragment/constructor/declaration.dart": (
+ hitCount: 248,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/constructor/encoding.dart": (
+ hitCount: 318,
+ missCount: 0,
+ ),
+ // 100.0%.
"package:front_end/src/fragment/enum.dart": (
hitCount: 13,
missCount: 0,
@@ -580,12 +590,12 @@
),
// 100.0%.
"package:front_end/src/kernel/body_builder.dart": (
- hitCount: 7181,
+ hitCount: 7180,
missCount: 0,
),
// 100.0%.
"package:front_end/src/kernel/body_builder_context.dart": (
- hitCount: 303,
+ hitCount: 289,
missCount: 0,
),
// 100.0%.
@@ -730,7 +740,7 @@
),
// 100.0%.
"package:front_end/src/kernel/kernel_target.dart": (
- hitCount: 1068,
+ hitCount: 1051,
missCount: 0,
),
// 100.0%.
@@ -860,12 +870,12 @@
),
// 100.0%.
"package:front_end/src/source/source_constructor_builder.dart": (
- hitCount: 1084,
+ hitCount: 722,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_enum_builder.dart": (
- hitCount: 420,
+ hitCount: 403,
missCount: 0,
),
// 100.0%.
@@ -931,7 +941,7 @@
),
// 100.0%.
"package:front_end/src/source/type_parameter_scope_builder.dart": (
- hitCount: 1395,
+ hitCount: 1408,
missCount: 0,
),
// 100.0%.
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 4409fb2..0271767 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -169,7 +169,7 @@
if (memberBuilder is SourcePropertyBuilder) {
patchMembers = memberBuilder.augmentationsForTesting;
}
- if (memberBuilder is DeclaredSourceConstructorBuilder) {
+ if (memberBuilder is SourceConstructorBuilderImpl) {
patchMembers = memberBuilder.augmentationsForTesting;
}
if (memberBuilder is SourceFactoryBuilder) {
diff --git a/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect b/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect
index 75dd9c6..85d6418 100644
--- a/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect
@@ -55,27 +55,35 @@
;
static extension-type-member method E1|constructor#_#new#tearOff(core::int foo) → self::E1% /* erasure=core::int, declared=! */
return self::E1|constructor#(foo);
-static extension-type-member method E1|constructor#named(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */
- ;
+static extension-type-member method E1|constructor#named(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */ {
+ lowered final self::E1% /* erasure=core::int, declared=! */ #this = foo;
+ return #this;
+}
static extension-type-member method E1|constructor#_#named#tearOff(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */
return self::E1|constructor#named(foo, bar);
static extension-type-member method E2|constructor#(core::int foo) → self::E2% /* erasure=core::int, declared=! */
;
static extension-type-member method E2|constructor#_#new#tearOff(core::int foo) → self::E2% /* erasure=core::int, declared=! */
return self::E2|constructor#(foo);
-static extension-type-member method E2|constructor#named(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */
- ;
+static extension-type-member method E2|constructor#named(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */ {
+ lowered final self::E2% /* erasure=core::int, declared=! */ #this = foo;
+ return #this;
+}
static extension-type-member method E2|constructor#_#named#tearOff(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */
return self::E2|constructor#named(foo, bar: bar);
static extension-type-member method E3|constructor#(core::int foo) → self::E3% /* erasure=core::int, declared=! */
;
static extension-type-member method E3|constructor#_#new#tearOff(core::int foo) → self::E3% /* erasure=core::int, declared=! */
return self::E3|constructor#(foo);
-static extension-type-member method E3|constructor#named(core::int foo, [has-declared-initializer invalid-type bar = null]) → self::E3% /* erasure=core::int, declared=! */
- ;
+static extension-type-member method E3|constructor#named(core::int foo, [has-declared-initializer invalid-type bar = null]) → self::E3% /* erasure=core::int, declared=! */ {
+ lowered final self::E3% /* erasure=core::int, declared=! */ #this = foo;
+ return #this;
+}
static extension-type-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3% /* erasure=core::int, declared=! */
return self::E3|constructor#named(foo, bar);
-static extension-type-member method E4|constructor#(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */
- ;
+static extension-type-member method E4|constructor#(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */ {
+ lowered final self::E4% /* erasure=invalid-type, declared=! */ #this = foo;
+ return #this;
+}
static extension-type-member method E4|constructor#_#new#tearOff(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */
return self::E4|constructor#(foo);
diff --git a/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect b/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect
index f44f65e..6e001c1 100644
--- a/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect
@@ -38,8 +38,10 @@
;
static extension-type-member method E07|constructor#_#new#tearOff(core::int x) → self::E07% /* erasure=core::int, declared=! */
return self::E07|constructor#(x);
-static extension-type-member method E08|constructor#(core::int x) → self::E08% /* erasure=core::int, declared=! */
- ;
+static extension-type-member method E08|constructor#(core::int x) → self::E08% /* erasure=core::int, declared=! */ {
+ lowered final self::E08% /* erasure=core::int, declared=! */ #this = x;
+ return #this;
+}
static extension-type-member method E08|constructor#_#new#tearOff(core::int x) → self::E08% /* erasure=core::int, declared=! */
return self::E08|constructor#(x);
static extension-type-member method E11|constructor#(() → core::int x) → self::E11% /* erasure=() → core::int, declared=! */