mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:31:58 +00:00
[cfe] Initial support for view constructors
Change-Id: I646c8e00cb819b5759f5df2b602f49a570d7f959 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/274220 Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
64fd5139e2
commit
6b73869b96
|
@ -57,8 +57,6 @@ abstract class ClassBuilder implements DeclarationBuilder {
|
|||
/// The types in the `on` clause of an extension or mixin declaration.
|
||||
List<TypeBuilder>? get onTypes;
|
||||
|
||||
ConstructorScope get constructorScope;
|
||||
|
||||
@override
|
||||
Uri get fileUri;
|
||||
|
||||
|
@ -170,9 +168,6 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
|
|||
@override
|
||||
List<TypeBuilder>? onTypes;
|
||||
|
||||
@override
|
||||
final ConstructorScope constructorScope;
|
||||
|
||||
@override
|
||||
bool isNullClass = false;
|
||||
|
||||
|
@ -190,10 +185,11 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
|
|||
this.interfaceBuilders,
|
||||
this.onTypes,
|
||||
Scope scope,
|
||||
this.constructorScope,
|
||||
ConstructorScope constructorScope,
|
||||
LibraryBuilder parent,
|
||||
int charOffset)
|
||||
: super(metadata, modifiers, name, parent, charOffset, scope);
|
||||
: super(metadata, modifiers, name, parent, charOffset, scope,
|
||||
constructorScope);
|
||||
|
||||
@override
|
||||
String get debugName => "ClassBuilder";
|
||||
|
|
|
@ -7,6 +7,11 @@ import 'package:kernel/ast.dart';
|
|||
import 'function_builder.dart';
|
||||
|
||||
abstract class ConstructorBuilder implements FunctionBuilder {
|
||||
/// The [Constructor] built by this builder.
|
||||
Constructor get constructor;
|
||||
/// The member target used for tearing of the constructor.
|
||||
@override
|
||||
Member get readTarget;
|
||||
|
||||
/// The member target used for calling the constructor.
|
||||
@override
|
||||
Member get invokeTarget;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ abstract class DeclarationBuilder implements TypeDeclarationBuilder {
|
|||
/// reported.
|
||||
Builder? lookupLocalMember(String name,
|
||||
{bool setter = false, bool required = false});
|
||||
|
||||
ConstructorScope get constructorScope;
|
||||
}
|
||||
|
||||
abstract class DeclarationBuilderImpl extends TypeDeclarationBuilderImpl
|
||||
|
@ -44,11 +46,20 @@ abstract class DeclarationBuilderImpl extends TypeDeclarationBuilderImpl
|
|||
@override
|
||||
final Scope scope;
|
||||
|
||||
@override
|
||||
final ConstructorScope constructorScope;
|
||||
|
||||
@override
|
||||
final Uri fileUri;
|
||||
|
||||
DeclarationBuilderImpl(List<MetadataBuilder>? metadata, int modifiers,
|
||||
String name, LibraryBuilder parent, int charOffset, this.scope)
|
||||
DeclarationBuilderImpl(
|
||||
List<MetadataBuilder>? metadata,
|
||||
int modifiers,
|
||||
String name,
|
||||
LibraryBuilder parent,
|
||||
int charOffset,
|
||||
this.scope,
|
||||
this.constructorScope)
|
||||
: fileUri = parent.fileUri,
|
||||
super(metadata, modifiers, name, parent, charOffset);
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@ abstract class ExtensionBuilderImpl extends DeclarationBuilderImpl
|
|||
implements ExtensionBuilder {
|
||||
ExtensionBuilderImpl(List<MetadataBuilder>? metadata, int modifiers,
|
||||
String name, LibraryBuilder parent, int charOffset, Scope scope)
|
||||
: super(metadata, modifiers, name, parent, charOffset, scope);
|
||||
: super(metadata, modifiers, name, parent, charOffset, scope,
|
||||
new ConstructorScope(name, const {}));
|
||||
|
||||
@override
|
||||
DartType buildAliasedTypeWithBuiltArguments(
|
||||
|
|
|
@ -23,6 +23,7 @@ import '../util/helpers.dart' show DelayedActionPerformer;
|
|||
import 'builder.dart';
|
||||
import 'class_builder.dart';
|
||||
import 'constructor_builder.dart';
|
||||
import 'declaration_builder.dart';
|
||||
import 'library_builder.dart';
|
||||
import 'metadata_builder.dart';
|
||||
import 'modifier_builder.dart';
|
||||
|
@ -220,8 +221,8 @@ class FormalParameterBuilder extends ModifierBuilderImpl
|
|||
}
|
||||
|
||||
void finalizeInitializingFormal(
|
||||
ClassBuilder classBuilder, ClassHierarchyBase hierarchy) {
|
||||
Builder? fieldBuilder = classBuilder.lookupLocalMember(name);
|
||||
DeclarationBuilder declarationBuilder, ClassHierarchyBase hierarchy) {
|
||||
Builder? fieldBuilder = declarationBuilder.lookupLocalMember(name);
|
||||
if (fieldBuilder is SourceFieldBuilder) {
|
||||
type.registerInferredType(fieldBuilder.inferType(hierarchy));
|
||||
} else {
|
||||
|
|
|
@ -45,9 +45,16 @@ abstract class ViewBuilder implements DeclarationBuilder {
|
|||
abstract class ViewBuilderImpl extends DeclarationBuilderImpl
|
||||
with DeclarationBuilderMixin
|
||||
implements ViewBuilder {
|
||||
ViewBuilderImpl(List<MetadataBuilder>? metadata, int modifiers, String name,
|
||||
LibraryBuilder parent, int charOffset, Scope scope)
|
||||
: super(metadata, modifiers, name, parent, charOffset, scope);
|
||||
ViewBuilderImpl(
|
||||
List<MetadataBuilder>? metadata,
|
||||
int modifiers,
|
||||
String name,
|
||||
LibraryBuilder parent,
|
||||
int charOffset,
|
||||
Scope scope,
|
||||
ConstructorScope constructorScope)
|
||||
: super(metadata, modifiers, name, parent, charOffset, scope,
|
||||
constructorScope);
|
||||
|
||||
@override
|
||||
DartType buildAliasedTypeWithBuiltArguments(
|
||||
|
|
|
@ -223,7 +223,6 @@ class DillFactoryBuilder extends DillProcedureBuilder {
|
|||
|
||||
class DillConstructorBuilder extends DillMemberBuilder
|
||||
implements ConstructorBuilder {
|
||||
@override
|
||||
final Constructor constructor;
|
||||
final Procedure? _constructorTearOff;
|
||||
|
||||
|
@ -238,7 +237,7 @@ class DillConstructorBuilder extends DillMemberBuilder
|
|||
Constructor get member => constructor;
|
||||
|
||||
@override
|
||||
Member? get readTarget => _constructorTearOff ?? constructor;
|
||||
Member get readTarget => _constructorTearOff ?? constructor;
|
||||
|
||||
@override
|
||||
Member? get writeTarget => null;
|
||||
|
|
|
@ -1290,7 +1290,7 @@ class BodyBuilder extends StackListenerImpl
|
|||
}
|
||||
}
|
||||
}
|
||||
if (builder is DeclaredSourceConstructorBuilder) {
|
||||
if (builder is AbstractSourceConstructorBuilder) {
|
||||
finishConstructor(builder, asyncModifier, body,
|
||||
superParametersAsArguments: superParametersAsArguments);
|
||||
} else if (builder is SourceProcedureBuilder) {
|
||||
|
@ -1829,8 +1829,8 @@ class BodyBuilder extends StackListenerImpl
|
|||
handleNoInitializers();
|
||||
}
|
||||
if (doFinishConstructor) {
|
||||
DeclaredSourceConstructorBuilder constructorBuilder =
|
||||
member as DeclaredSourceConstructorBuilder;
|
||||
AbstractSourceConstructorBuilder constructorBuilder =
|
||||
member as AbstractSourceConstructorBuilder;
|
||||
List<FormalParameterBuilder>? formals = constructorBuilder.formals;
|
||||
finishConstructor(constructorBuilder, AsyncMarker.Sync, null,
|
||||
superParametersAsArguments: formals != null
|
||||
|
@ -1879,14 +1879,14 @@ class BodyBuilder extends StackListenerImpl
|
|||
return arguments;
|
||||
}
|
||||
|
||||
void finishConstructor(DeclaredSourceConstructorBuilder builder,
|
||||
void finishConstructor(AbstractSourceConstructorBuilder builder,
|
||||
AsyncMarker asyncModifier, Statement? body,
|
||||
{required List<Object /* Expression | NamedExpression */ >?
|
||||
superParametersAsArguments}) {
|
||||
/// Quotes below are from [Dart Programming Language Specification, 4th
|
||||
/// Edition](
|
||||
/// https://ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf).
|
||||
assert(builder == member);
|
||||
assert(builder == this.member);
|
||||
assert(() {
|
||||
if (superParametersAsArguments == null) {
|
||||
return true;
|
||||
|
@ -1925,7 +1925,8 @@ class BodyBuilder extends StackListenerImpl
|
|||
"Expected 'superParametersAsArguments' "
|
||||
"to be sorted by occurrence in file.");
|
||||
|
||||
Constructor constructor = builder.actualConstructor;
|
||||
Member member = builder.member;
|
||||
FunctionNode function = builder.function;
|
||||
List<FormalParameterBuilder>? formals = builder.formals;
|
||||
if (formals != null) {
|
||||
for (int i = 0; i < formals.length; i++) {
|
||||
|
@ -1983,11 +1984,11 @@ class BodyBuilder extends StackListenerImpl
|
|||
if (initializers.last is SuperInitializer) {
|
||||
SuperInitializer superInitializer =
|
||||
initializers.last as SuperInitializer;
|
||||
if (builder.classBuilder.isEnum) {
|
||||
if (builder.declarationBuilder.isEnum) {
|
||||
initializers[initializers.length - 1] = buildInvalidInitializer(
|
||||
buildProblem(fasta.messageEnumConstructorSuperInitializer,
|
||||
superInitializer.fileOffset, noLength))
|
||||
..parent = constructor;
|
||||
..parent = member;
|
||||
} else if (libraryFeatures.superParameters.isEnabled) {
|
||||
ArgumentsImpl arguments = superInitializer.arguments as ArgumentsImpl;
|
||||
|
||||
|
@ -2029,10 +2030,10 @@ class BodyBuilder extends StackListenerImpl
|
|||
ArgumentsImpl arguments =
|
||||
redirectingInitializer.arguments as ArgumentsImpl;
|
||||
List<Expression> enumSyntheticArguments = [
|
||||
new VariableGetImpl(constructor.function.positionalParameters[0],
|
||||
new VariableGetImpl(function.positionalParameters[0],
|
||||
forNullGuardedAccess: false)
|
||||
..parent = redirectingInitializer.arguments,
|
||||
new VariableGetImpl(constructor.function.positionalParameters[1],
|
||||
new VariableGetImpl(function.positionalParameters[1],
|
||||
forNullGuardedAccess: false)
|
||||
..parent = redirectingInitializer.arguments
|
||||
];
|
||||
|
@ -2057,8 +2058,9 @@ class BodyBuilder extends StackListenerImpl
|
|||
}
|
||||
}
|
||||
|
||||
List<Initializer> builtInitializers = builder.initializers;
|
||||
if (asyncModifier != AsyncMarker.Sync) {
|
||||
constructor.initializers.add(buildInvalidInitializer(buildProblem(
|
||||
builtInitializers.add(buildInvalidInitializer(buildProblem(
|
||||
fasta.messageConstructorNotSync, body!.fileOffset, noLength)));
|
||||
}
|
||||
if (needsImplicitSuperInitializer) {
|
||||
|
@ -2075,13 +2077,13 @@ class BodyBuilder extends StackListenerImpl
|
|||
namedArguments = namedSuperParametersAsArguments;
|
||||
}
|
||||
if (sourceClassBuilder is SourceEnumBuilder) {
|
||||
assert(constructor.function.positionalParameters.length >= 2 &&
|
||||
constructor.function.positionalParameters[0].name == "#index" &&
|
||||
constructor.function.positionalParameters[1].name == "#name");
|
||||
assert(function.positionalParameters.length >= 2 &&
|
||||
function.positionalParameters[0].name == "#index" &&
|
||||
function.positionalParameters[1].name == "#name");
|
||||
(positionalArguments ??= <Expression>[]).insertAll(0, [
|
||||
new VariableGetImpl(constructor.function.positionalParameters[0],
|
||||
new VariableGetImpl(function.positionalParameters[0],
|
||||
forNullGuardedAccess: false),
|
||||
new VariableGetImpl(constructor.function.positionalParameters[1],
|
||||
new VariableGetImpl(function.positionalParameters[1],
|
||||
forNullGuardedAccess: false)
|
||||
]);
|
||||
}
|
||||
|
@ -2104,9 +2106,9 @@ class BodyBuilder extends StackListenerImpl
|
|||
null) {
|
||||
String superclass =
|
||||
sourceClassBuilder!.supertypeBuilder!.fullNameForErrors;
|
||||
int length = constructor.name.text.length;
|
||||
int length = builder.name.length;
|
||||
if (length == 0) {
|
||||
length = (constructor.parent as Class).name.length;
|
||||
length = sourceClassBuilder!.cls.name.length;
|
||||
}
|
||||
initializer = buildInvalidInitializer(
|
||||
buildProblem(
|
||||
|
@ -2125,16 +2127,15 @@ class BodyBuilder extends StackListenerImpl
|
|||
builder.addInitializer(initializer, this,
|
||||
inferenceResult: inferenceResult);
|
||||
} else {
|
||||
constructor.initializers.add(initializer);
|
||||
builtInitializers.add(initializer);
|
||||
}
|
||||
}
|
||||
setParents(constructor.initializers, constructor);
|
||||
setParents(builtInitializers, member);
|
||||
if (body == null) {
|
||||
/// >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.
|
||||
constructor.function.body = new EmptyStatement()
|
||||
..parent = constructor.function;
|
||||
function.body = new EmptyStatement()..parent = function;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,10 +101,12 @@ Procedure? createConstructorTearOffProcedure(
|
|||
Uri fileUri,
|
||||
int fileOffset,
|
||||
Reference? reference,
|
||||
{required bool forAbstractClassOrEnum}) {
|
||||
{required bool forAbstractClassOrEnum,
|
||||
bool forceCreateLowering = false}) {
|
||||
if (!forAbstractClassOrEnum &&
|
||||
compilationUnit
|
||||
.loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
|
||||
(forceCreateLowering ||
|
||||
compilationUnit.loader.target.backendTarget
|
||||
.isConstructorTearOffLoweringEnabled)) {
|
||||
return _createTearOffProcedure(compilationUnit,
|
||||
constructorTearOffName(name), fileUri, fileOffset, reference);
|
||||
}
|
||||
|
@ -144,7 +146,8 @@ Procedure createTypedefTearOffProcedure(
|
|||
}
|
||||
|
||||
/// Creates the parameters and body for [tearOff] based on
|
||||
/// [declarationConstructor] in [enclosingClass].
|
||||
/// [declarationConstructor].
|
||||
/// [enclosingDeclarationTypeParameters].
|
||||
///
|
||||
/// The [declarationConstructor] is the origin constructor and
|
||||
/// [implementationConstructor] is the patch constructor, if patched, otherwise
|
||||
|
@ -153,7 +156,7 @@ void buildConstructorTearOffProcedure(
|
|||
{required Procedure tearOff,
|
||||
required Member declarationConstructor,
|
||||
required Member implementationConstructor,
|
||||
required Class enclosingClass,
|
||||
List<TypeParameter>? enclosingDeclarationTypeParameters,
|
||||
required SourceLibraryBuilder libraryBuilder}) {
|
||||
assert(
|
||||
declarationConstructor is Constructor ||
|
||||
|
@ -176,19 +179,15 @@ void buildConstructorTearOffProcedure(
|
|||
|
||||
int fileOffset = tearOff.fileOffset;
|
||||
|
||||
List<TypeParameter> classTypeParameters;
|
||||
if (declarationConstructor is Constructor) {
|
||||
// Generative constructors implicitly have the type parameters of the
|
||||
// enclosing class.
|
||||
classTypeParameters = enclosingClass.typeParameters;
|
||||
} else {
|
||||
// Factory constructors explicitly copy over the type parameters of the
|
||||
// enclosing class.
|
||||
classTypeParameters = function.typeParameters;
|
||||
}
|
||||
List<TypeParameter> declarationTypeParameters =
|
||||
enclosingDeclarationTypeParameters ?? function.typeParameters;
|
||||
|
||||
FreshTypeParameters freshTypeParameters =
|
||||
_createFreshTypeParameters(classTypeParameters, tearOff.function);
|
||||
_createFreshTypeParameters(declarationTypeParameters, tearOff.function);
|
||||
|
||||
List<DartType> typeArguments = freshTypeParameters.freshTypeArguments;
|
||||
Substitution substitution = freshTypeParameters.substitution;
|
||||
|
|
|
@ -1087,7 +1087,7 @@ class KernelTarget extends TargetImplementation {
|
|||
tearOff: constructorTearOff,
|
||||
declarationConstructor: constructor,
|
||||
implementationConstructor: constructor,
|
||||
enclosingClass: classBuilder.cls,
|
||||
enclosingDeclarationTypeParameters: classBuilder.cls.typeParameters,
|
||||
libraryBuilder: classBuilder.libraryBuilder);
|
||||
}
|
||||
SyntheticSourceConstructorBuilder constructorBuilder =
|
||||
|
@ -1166,7 +1166,7 @@ class KernelTarget extends TargetImplementation {
|
|||
tearOff: constructorTearOff,
|
||||
declarationConstructor: constructor,
|
||||
implementationConstructor: constructor,
|
||||
enclosingClass: classBuilder.cls,
|
||||
enclosingDeclarationTypeParameters: classBuilder.cls.typeParameters,
|
||||
libraryBuilder: classBuilder.libraryBuilder);
|
||||
}
|
||||
return new SyntheticSourceConstructorBuilder(
|
||||
|
@ -1404,7 +1404,7 @@ class KernelTarget extends TargetImplementation {
|
|||
}
|
||||
}
|
||||
|
||||
Map<ConstructorBuilder, Set<SourceFieldBuilder>>
|
||||
Map<DeclaredSourceConstructorBuilder, Set<SourceFieldBuilder>>
|
||||
constructorInitializedFields = new Map.identity();
|
||||
Set<SourceFieldBuilder>? initializedFields = null;
|
||||
|
||||
|
@ -1467,7 +1467,8 @@ class KernelTarget extends TargetImplementation {
|
|||
|
||||
// Run through all fields that are initialized by some constructor, and
|
||||
// make sure that all other constructors also initialize them.
|
||||
constructorInitializedFields.forEach((ConstructorBuilder constructorBuilder,
|
||||
constructorInitializedFields.forEach(
|
||||
(DeclaredSourceConstructorBuilder constructorBuilder,
|
||||
Set<FieldBuilder> fieldBuilders) {
|
||||
for (SourceFieldBuilder fieldBuilder
|
||||
in initializedFields!.difference(fieldBuilders)) {
|
||||
|
|
|
@ -51,11 +51,13 @@ import '../type_inference/type_inference_engine.dart'
|
|||
show InferenceDataForTesting, TypeInferenceEngine;
|
||||
import '../type_inference/type_inferrer.dart' show TypeInferrer;
|
||||
import 'diet_parser.dart';
|
||||
import 'source_class_builder.dart';
|
||||
import 'source_constructor_builder.dart';
|
||||
import 'source_enum_builder.dart';
|
||||
import 'source_field_builder.dart';
|
||||
import 'source_function_builder.dart';
|
||||
import 'source_library_builder.dart' show SourceLibraryBuilder;
|
||||
import 'source_view_builder.dart';
|
||||
import 'stack_listener_impl.dart';
|
||||
|
||||
class DietListener extends StackListenerImpl {
|
||||
|
@ -729,10 +731,9 @@ class DietListener extends StackListenerImpl {
|
|||
Token? metadata = pop() as Token?;
|
||||
checkEmpty(beginToken.charOffset);
|
||||
if (name is ParserRecovery || currentClassIsParserRecovery) return;
|
||||
SourceFunctionBuilderImpl builder;
|
||||
SourceFunctionBuilder builder;
|
||||
if (isConstructor) {
|
||||
builder =
|
||||
lookupConstructor(beginToken, name!) as SourceFunctionBuilderImpl;
|
||||
builder = lookupConstructor(beginToken, name!) as SourceFunctionBuilder;
|
||||
} else {
|
||||
Builder? memberBuilder =
|
||||
lookupBuilder(beginToken, getOrSet, name as String);
|
||||
|
@ -745,7 +746,7 @@ class DietListener extends StackListenerImpl {
|
|||
// this point we skip the member.
|
||||
return;
|
||||
}
|
||||
builder = memberBuilder as SourceFunctionBuilderImpl;
|
||||
builder = memberBuilder as SourceFunctionBuilder;
|
||||
}
|
||||
buildFunctionBody(
|
||||
createFunctionListener(builder),
|
||||
|
@ -809,7 +810,7 @@ class DietListener extends StackListenerImpl {
|
|||
..constantContext = constantContext;
|
||||
}
|
||||
|
||||
BodyBuilder createFunctionListener(SourceFunctionBuilderImpl builder) {
|
||||
BodyBuilder createFunctionListener(SourceFunctionBuilder builder) {
|
||||
final Scope typeParameterScope =
|
||||
builder.computeTypeParameterScope(memberScope);
|
||||
final Scope formalParameterScope =
|
||||
|
@ -1166,20 +1167,23 @@ class DietListener extends StackListenerImpl {
|
|||
}
|
||||
|
||||
Builder? lookupConstructor(Token token, Object nameOrQualified) {
|
||||
assert(currentClass != null);
|
||||
assert(currentDeclaration != null);
|
||||
assert(currentDeclaration is SourceClassBuilder ||
|
||||
currentDeclaration is SourceViewBuilder);
|
||||
Builder? declaration;
|
||||
String suffix;
|
||||
if (nameOrQualified is QualifiedName) {
|
||||
suffix = nameOrQualified.name;
|
||||
} else {
|
||||
suffix = nameOrQualified == currentClass!.name
|
||||
suffix = nameOrQualified == currentDeclaration!.name
|
||||
? ""
|
||||
: nameOrQualified as String;
|
||||
}
|
||||
if (libraryFeatures.constructorTearoffs.isEnabled) {
|
||||
suffix = suffix == "new" ? "" : suffix;
|
||||
}
|
||||
declaration = currentClass!.constructorScope.lookupLocalMember(suffix);
|
||||
declaration =
|
||||
currentDeclaration!.constructorScope.lookupLocalMember(suffix);
|
||||
declaration = handleDuplicatedName(declaration, token);
|
||||
checkBuilder(token, declaration, nameOrQualified);
|
||||
return declaration;
|
||||
|
|
|
@ -151,8 +151,20 @@ class NameScheme {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Use [NameScheme] for constructor and constructor
|
||||
// tear-off names.
|
||||
MemberName getConstructorMemberName(String name, {required bool isTearOff}) {
|
||||
switch (containerType) {
|
||||
case ContainerType.Library:
|
||||
case ContainerType.Class:
|
||||
return name.startsWith('_')
|
||||
? new PrivateMemberName(libraryName, name)
|
||||
: new PublicMemberName(name);
|
||||
case ContainerType.View:
|
||||
case ContainerType.Extension:
|
||||
// Extension is handled here for the error case only.
|
||||
return new ViewConstructorName(libraryName, containerName!, name,
|
||||
isTearOff: isTearOff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The part of a member name defined by a library.
|
||||
|
@ -395,8 +407,8 @@ class PrivateMemberName extends UpdatableMemberName {
|
|||
|
||||
/// A name for an extension procedure.
|
||||
///
|
||||
/// This depends on a [LibraryName] and an [ExtensionName] and is updated the
|
||||
/// reference of the [LibraryName] or the name of the [ExtensionName] is
|
||||
/// This depends on a [LibraryName] and an [ContainerName] and is updated the
|
||||
/// reference of the [LibraryName] or the name of the [ContainerName] is
|
||||
/// changed.
|
||||
class ExtensionProcedureName extends UpdatableMemberName {
|
||||
final LibraryName _libraryName;
|
||||
|
@ -426,6 +438,40 @@ class ExtensionProcedureName extends UpdatableMemberName {
|
|||
}
|
||||
}
|
||||
|
||||
/// A name for a view constructor.
|
||||
///
|
||||
/// This depends on a [LibraryName] and an [ContainerName] and is updated the
|
||||
/// reference of the [LibraryName] or the name of the [ContainerName] is
|
||||
/// changed.
|
||||
class ViewConstructorName extends UpdatableMemberName {
|
||||
final LibraryName _libraryName;
|
||||
final ContainerName _containerName;
|
||||
final bool isTearOff;
|
||||
final String _text;
|
||||
|
||||
ViewConstructorName(this._libraryName, this._containerName, this._text,
|
||||
{required this.isTearOff}) {
|
||||
_libraryName.attachMemberName(this);
|
||||
_containerName.attachMemberName(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Name _createName() {
|
||||
String viewName = _containerName.name;
|
||||
String kindInfix;
|
||||
// Constructors and tear-offs are converted to methods so we use an
|
||||
// infix to make their names unique.
|
||||
if (isTearOff) {
|
||||
kindInfix = 'get#';
|
||||
} else {
|
||||
kindInfix = '';
|
||||
}
|
||||
|
||||
return new Name.byReference(
|
||||
'${viewName}|${kindInfix}${_text}', _libraryName.reference);
|
||||
}
|
||||
}
|
||||
|
||||
/// A name of a synthesized field.
|
||||
///
|
||||
/// This depends on a [LibraryName] and an [ExtensionName] and is updated the
|
||||
|
|
|
@ -19,6 +19,7 @@ import '../kernel/kernel_helper.dart';
|
|||
import '../problems.dart';
|
||||
import '../scope.dart';
|
||||
import '../util/helpers.dart';
|
||||
import 'source_constructor_builder.dart';
|
||||
import 'source_field_builder.dart';
|
||||
import 'source_library_builder.dart';
|
||||
import 'source_member_builder.dart';
|
||||
|
@ -88,6 +89,7 @@ mixin SourceDeclarationBuilderMixin
|
|||
}
|
||||
|
||||
scope.unfilteredNameIterator.forEach(buildBuilders);
|
||||
constructorScope.unfilteredNameIterator.forEach(buildBuilders);
|
||||
}
|
||||
|
||||
int buildBodyNodes({required bool addMembersToLibrary}) {
|
||||
|
@ -122,6 +124,8 @@ mixin SourceDeclarationBuilderMixin
|
|||
setterDeclaration as ProcedureBuilder, typeEnvironment);
|
||||
}
|
||||
}
|
||||
} else if (builder is SourceConstructorBuilder) {
|
||||
builder.checkTypes(libraryBuilder, typeEnvironment);
|
||||
} else {
|
||||
assert(false, "Unexpected member: $builder.");
|
||||
}
|
||||
|
|
|
@ -1134,8 +1134,7 @@ class SourceClassBuilder extends ClassBuilderImpl
|
|||
// Synthetic constructors are created after the component has been built
|
||||
// so we need to add the constructor to the class.
|
||||
cls.addConstructor(constructorBuilder.invokeTarget);
|
||||
if (constructorBuilder.readTarget != null &&
|
||||
constructorBuilder.readTarget != constructorBuilder.invokeTarget) {
|
||||
if (constructorBuilder.readTarget != constructorBuilder.invokeTarget) {
|
||||
cls.addProcedure(constructorBuilder.readTarget as Procedure);
|
||||
}
|
||||
if (constructorBuilder.isConst) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:kernel/type_environment.dart';
|
|||
import '../builder/builder.dart';
|
||||
import '../builder/class_builder.dart';
|
||||
import '../builder/constructor_builder.dart';
|
||||
import '../builder/declaration_builder.dart';
|
||||
import '../builder/formal_parameter_builder.dart';
|
||||
import '../builder/member_builder.dart';
|
||||
import '../builder/metadata_builder.dart';
|
||||
|
@ -55,9 +56,12 @@ import '../util/helpers.dart' show DelayedActionPerformer;
|
|||
import 'name_scheme.dart';
|
||||
import 'source_field_builder.dart';
|
||||
import 'source_function_builder.dart';
|
||||
import 'source_view_builder.dart';
|
||||
|
||||
abstract class SourceConstructorBuilder
|
||||
implements ConstructorBuilder, SourceMemberBuilder {
|
||||
DeclarationBuilder get declarationBuilder;
|
||||
|
||||
/// Infers the types of any untyped initializing formals.
|
||||
void inferFormalTypes(ClassHierarchyBase hierarchy);
|
||||
|
||||
|
@ -72,87 +76,33 @@ abstract class SourceConstructorBuilder
|
|||
bool get isRedirecting;
|
||||
}
|
||||
|
||||
class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
||||
abstract class AbstractSourceConstructorBuilder
|
||||
extends SourceFunctionBuilderImpl
|
||||
implements SourceConstructorBuilder, Inferable {
|
||||
@override
|
||||
final OmittedTypeBuilder returnType;
|
||||
|
||||
late final Constructor _constructor;
|
||||
late final Procedure? _constructorTearOff;
|
||||
|
||||
Set<SourceFieldBuilder>? _initializedFields;
|
||||
|
||||
final int charOpenParenOffset;
|
||||
|
||||
bool hasMovedSuperInitializer = false;
|
||||
|
||||
SuperInitializer? superInitializer;
|
||||
|
||||
RedirectingInitializer? redirectingInitializer;
|
||||
|
||||
Token? beginInitializers;
|
||||
|
||||
DeclaredSourceConstructorBuilder? actualOrigin;
|
||||
|
||||
Constructor get actualConstructor => _constructor;
|
||||
|
||||
List<DeclaredSourceConstructorBuilder>? _patches;
|
||||
|
||||
bool _hasFormalsInferred = false;
|
||||
|
||||
bool _hasDefaultValueCloner = false;
|
||||
Token? beginInitializers;
|
||||
|
||||
final bool _hasSuperInitializingFormals;
|
||||
|
||||
final List<DelayedDefaultValueCloner> _superParameterDefaultValueCloners =
|
||||
<DelayedDefaultValueCloner>[];
|
||||
|
||||
@override
|
||||
List<FormalParameterBuilder>? formals;
|
||||
|
||||
@override
|
||||
String get fullNameForErrors {
|
||||
return "${flattenName(classBuilder.name, charOffset, fileUri)}"
|
||||
"${name.isEmpty ? '' : '.$name'}";
|
||||
}
|
||||
|
||||
DeclaredSourceConstructorBuilder(
|
||||
AbstractSourceConstructorBuilder(
|
||||
List<MetadataBuilder>? metadata,
|
||||
int modifiers,
|
||||
this.returnType,
|
||||
String name,
|
||||
List<TypeVariableBuilder>? typeVariables,
|
||||
this.formals,
|
||||
List<FormalParameterBuilder>? formals,
|
||||
SourceLibraryBuilder compilationUnit,
|
||||
int startCharOffset,
|
||||
int charOffset,
|
||||
this.charOpenParenOffset,
|
||||
int charEndOffset,
|
||||
Reference? constructorReference,
|
||||
Reference? tearOffReference,
|
||||
{String? nativeMethodName,
|
||||
required bool forAbstractClassOrEnum})
|
||||
: _hasSuperInitializingFormals =
|
||||
formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
|
||||
super(metadata, modifiers, name, typeVariables, formals,
|
||||
String? nativeMethodName)
|
||||
: super(metadata, modifiers, name, typeVariables, formals,
|
||||
compilationUnit, charOffset, nativeMethodName) {
|
||||
_constructor = new Constructor(new FunctionNode(null),
|
||||
name: dummyName,
|
||||
fileUri: compilationUnit.fileUri,
|
||||
reference: constructorReference)
|
||||
..startFileOffset = startCharOffset
|
||||
..fileOffset = charOffset
|
||||
..fileEndOffset = charEndOffset
|
||||
..isNonNullableByDefault = compilationUnit.isNonNullableByDefault;
|
||||
MemberName constructorName =
|
||||
new MemberName(compilationUnit.libraryName, name);
|
||||
constructorName.attachMember(_constructor);
|
||||
_constructorTearOff = createConstructorTearOffProcedure(name,
|
||||
compilationUnit, compilationUnit.fileUri, charOffset, tearOffReference,
|
||||
forAbstractClassOrEnum: forAbstractClassOrEnum);
|
||||
|
||||
if (formals != null) {
|
||||
for (FormalParameterBuilder formal in formals!) {
|
||||
for (FormalParameterBuilder formal in formals) {
|
||||
if (formal.isInitializingFormal || formal.isSuperInitializingFormal) {
|
||||
formal.type.registerInferable(this);
|
||||
}
|
||||
|
@ -160,12 +110,292 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
DeclarationBuilder get declarationBuilder => super.declarationBuilder!;
|
||||
|
||||
@override
|
||||
bool get isConstructor => true;
|
||||
|
||||
@override
|
||||
ProcedureKind? get kind => null;
|
||||
|
||||
@override
|
||||
AsyncMarker get asyncModifier => AsyncMarker.Sync;
|
||||
|
||||
@override
|
||||
void inferTypes(ClassHierarchyBase hierarchy) {
|
||||
inferFormalTypes(hierarchy);
|
||||
}
|
||||
|
||||
@override
|
||||
void inferFormalTypes(ClassHierarchyBase hierarchy) {
|
||||
if (_hasFormalsInferred) return;
|
||||
if (formals != null) {
|
||||
libraryBuilder.loader.withUriForCrashReporting(fileUri, charOffset, () {
|
||||
for (FormalParameterBuilder formal in formals!) {
|
||||
if (formal.type is InferableTypeBuilder) {
|
||||
if (formal.isInitializingFormal) {
|
||||
formal.finalizeInitializingFormal(declarationBuilder, hierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
_inferSuperInitializingFormals(hierarchy);
|
||||
});
|
||||
}
|
||||
_hasFormalsInferred = true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@override
|
||||
bool get isRedirecting {
|
||||
for (Initializer initializer in initializers) {
|
||||
if (initializer is RedirectingInitializer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _injectInvalidInitializer(Message message, int charOffset, int length,
|
||||
ExpressionGeneratorHelper helper) {
|
||||
Initializer lastInitializer = initializers.removeLast();
|
||||
assert(lastInitializer == superInitializer ||
|
||||
lastInitializer == redirectingInitializer);
|
||||
Initializer error = helper.buildInvalidInitializer(
|
||||
helper.buildProblem(message, charOffset, length));
|
||||
initializers.add(error..parent = member);
|
||||
initializers.add(lastInitializer);
|
||||
}
|
||||
|
||||
SuperInitializer? superInitializer;
|
||||
|
||||
RedirectingInitializer? redirectingInitializer;
|
||||
|
||||
void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
|
||||
{required InitializerInferenceResult? inferenceResult}) {
|
||||
if (initializer is SuperInitializer) {
|
||||
if (superInitializer != null) {
|
||||
_injectInvalidInitializer(messageMoreThanOneSuperInitializer,
|
||||
initializer.fileOffset, "super".length, helper);
|
||||
} else if (redirectingInitializer != null) {
|
||||
_injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithSuperInitializer,
|
||||
initializer.fileOffset,
|
||||
"super".length,
|
||||
helper);
|
||||
} else {
|
||||
inferenceResult?.applyResult(initializers, member);
|
||||
superInitializer = initializer;
|
||||
|
||||
LocatedMessage? message = helper.checkArgumentsForFunction(
|
||||
initializer.target.function,
|
||||
initializer.arguments,
|
||||
initializer.arguments.fileOffset, <TypeParameter>[]);
|
||||
if (message != null) {
|
||||
initializers.add(helper.buildInvalidInitializer(
|
||||
helper.buildUnresolvedError(
|
||||
helper.constructorNameForDiagnostics(
|
||||
initializer.target.name.text),
|
||||
initializer.fileOffset,
|
||||
arguments: initializer.arguments,
|
||||
isSuper: true,
|
||||
message: message,
|
||||
kind: UnresolvedKind.Constructor))
|
||||
..parent = member);
|
||||
} else {
|
||||
initializers.add(initializer..parent = member);
|
||||
}
|
||||
}
|
||||
} else if (initializer is RedirectingInitializer) {
|
||||
if (superInitializer != null) {
|
||||
// Point to the existing super initializer.
|
||||
_injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithSuperInitializer,
|
||||
superInitializer!.fileOffset,
|
||||
"super".length,
|
||||
helper);
|
||||
} else if (redirectingInitializer != null) {
|
||||
_injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithMultipleRedirectInitializers,
|
||||
initializer.fileOffset,
|
||||
noLength,
|
||||
helper);
|
||||
} else if (initializers.isNotEmpty) {
|
||||
// Error on all previous ones.
|
||||
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(
|
||||
helper.buildProblem(
|
||||
messageRedirectingConstructorWithAnotherInitializer,
|
||||
initializer.fileOffset,
|
||||
length));
|
||||
error.parent = member;
|
||||
initializers[i] = error;
|
||||
}
|
||||
inferenceResult?.applyResult(initializers, member);
|
||||
initializers.add(initializer..parent = member);
|
||||
redirectingInitializer = initializer;
|
||||
} else {
|
||||
inferenceResult?.applyResult(initializers, member);
|
||||
redirectingInitializer = initializer;
|
||||
|
||||
LocatedMessage? message = helper.checkArgumentsForFunction(
|
||||
initializer.target.function,
|
||||
initializer.arguments,
|
||||
initializer.arguments.fileOffset, const <TypeParameter>[]);
|
||||
if (message != null) {
|
||||
initializers.add(helper.buildInvalidInitializer(
|
||||
helper.buildUnresolvedError(
|
||||
helper.constructorNameForDiagnostics(
|
||||
initializer.target.name.text,
|
||||
isSuper: false),
|
||||
initializer.fileOffset,
|
||||
arguments: initializer.arguments,
|
||||
isSuper: false,
|
||||
message: message,
|
||||
kind: UnresolvedKind.Constructor))
|
||||
..parent = member);
|
||||
} else {
|
||||
initializers.add(initializer..parent = member);
|
||||
}
|
||||
}
|
||||
} else if (redirectingInitializer != null) {
|
||||
int length = noLength;
|
||||
if (initializer is AssertInitializer) length = "assert".length;
|
||||
_injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithAnotherInitializer,
|
||||
initializer.fileOffset,
|
||||
length,
|
||||
helper);
|
||||
} else if (superInitializer != null) {
|
||||
_injectInvalidInitializer(messageSuperInitializerNotLast,
|
||||
initializer.fileOffset, noLength, helper);
|
||||
} else {
|
||||
inferenceResult?.applyResult(initializers, member);
|
||||
initializers.add(initializer..parent = member);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void checkVariance(
|
||||
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {}
|
||||
|
||||
@override
|
||||
void checkTypes(
|
||||
SourceLibraryBuilder library, TypeEnvironment typeEnvironment) {
|
||||
library.checkTypesInConstructorBuilder(this, formals, typeEnvironment);
|
||||
}
|
||||
|
||||
@override
|
||||
List<ClassMember> get localMembers =>
|
||||
throw new UnsupportedError('${runtimeType}.localMembers');
|
||||
|
||||
@override
|
||||
List<ClassMember> get localSetters =>
|
||||
throw new UnsupportedError('${runtimeType}.localSetters');
|
||||
}
|
||||
|
||||
class DeclaredSourceConstructorBuilder
|
||||
extends AbstractSourceConstructorBuilder {
|
||||
late final Constructor _constructor;
|
||||
late final Procedure? _constructorTearOff;
|
||||
|
||||
Set<SourceFieldBuilder>? _initializedFields;
|
||||
|
||||
DeclaredSourceConstructorBuilder? actualOrigin;
|
||||
|
||||
Constructor get actualConstructor => _constructor;
|
||||
|
||||
List<DeclaredSourceConstructorBuilder>? _patches;
|
||||
|
||||
bool _hasDefaultValueCloner = false;
|
||||
|
||||
@override
|
||||
List<FormalParameterBuilder>? formals;
|
||||
|
||||
@override
|
||||
String get fullNameForErrors {
|
||||
return "${flattenName(declarationBuilder.name, charOffset, fileUri)}"
|
||||
"${name.isEmpty ? '' : '.$name'}";
|
||||
}
|
||||
|
||||
DeclaredSourceConstructorBuilder(
|
||||
List<MetadataBuilder>? metadata,
|
||||
int modifiers,
|
||||
OmittedTypeBuilder returnType,
|
||||
String name,
|
||||
List<TypeVariableBuilder>? typeVariables,
|
||||
this.formals,
|
||||
SourceLibraryBuilder compilationUnit,
|
||||
int startCharOffset,
|
||||
int charOffset,
|
||||
int charOpenParenOffset,
|
||||
int charEndOffset,
|
||||
Reference? constructorReference,
|
||||
Reference? tearOffReference,
|
||||
NameScheme nameScheme,
|
||||
{String? nativeMethodName,
|
||||
required bool forAbstractClassOrEnum})
|
||||
: _hasSuperInitializingFormals =
|
||||
formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
|
||||
super(
|
||||
metadata,
|
||||
modifiers,
|
||||
returnType,
|
||||
name,
|
||||
typeVariables,
|
||||
formals,
|
||||
compilationUnit,
|
||||
charOffset,
|
||||
charOpenParenOffset,
|
||||
nativeMethodName) {
|
||||
_constructor = new Constructor(new FunctionNode(null),
|
||||
name: dummyName,
|
||||
fileUri: compilationUnit.fileUri,
|
||||
reference: constructorReference)
|
||||
..startFileOffset = startCharOffset
|
||||
..fileOffset = charOffset
|
||||
..fileEndOffset = charEndOffset
|
||||
..isNonNullableByDefault = compilationUnit.isNonNullableByDefault;
|
||||
nameScheme
|
||||
.getConstructorMemberName(name, isTearOff: false)
|
||||
.attachMember(_constructor);
|
||||
_constructorTearOff = createConstructorTearOffProcedure(name,
|
||||
compilationUnit, compilationUnit.fileUri, charOffset, tearOffReference,
|
||||
forAbstractClassOrEnum: forAbstractClassOrEnum);
|
||||
// TODO(johnniwinther): Use [NameScheme] for constructor tear-off names.
|
||||
}
|
||||
|
||||
@override
|
||||
SourceClassBuilder get classBuilder =>
|
||||
super.classBuilder as SourceClassBuilder;
|
||||
|
||||
@override
|
||||
Member? get readTarget => _constructorTearOff ?? _constructor;
|
||||
Member get readTarget => _constructorTearOff ?? _constructor;
|
||||
|
||||
@override
|
||||
Member? get writeTarget => null;
|
||||
|
@ -179,6 +409,9 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
@override
|
||||
Iterable<Member> get exportedMembers => [constructor];
|
||||
|
||||
@override
|
||||
List<Initializer> get initializers => _constructor.initializers;
|
||||
|
||||
@override
|
||||
DeclaredSourceConstructorBuilder get origin => actualOrigin ?? this;
|
||||
|
||||
|
@ -190,25 +423,6 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
@override
|
||||
bool get isClassInstanceMember => false;
|
||||
|
||||
@override
|
||||
bool get isConstructor => true;
|
||||
|
||||
@override
|
||||
AsyncMarker get asyncModifier => AsyncMarker.Sync;
|
||||
|
||||
@override
|
||||
ProcedureKind? get kind => null;
|
||||
|
||||
@override
|
||||
bool get isRedirecting {
|
||||
for (Initializer initializer in _constructor.initializers) {
|
||||
if (initializer is RedirectingInitializer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns `true` if this constructor, including its augmentations, is
|
||||
/// external.
|
||||
///
|
||||
|
@ -272,29 +486,13 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
tearOff: _constructorTearOff!,
|
||||
declarationConstructor: constructor,
|
||||
implementationConstructor: _constructor,
|
||||
enclosingClass: classBuilder.cls,
|
||||
enclosingDeclarationTypeParameters: classBuilder.cls.typeParameters,
|
||||
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, this);
|
||||
}
|
||||
}
|
||||
_buildFormals(_constructor);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -306,47 +504,9 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void inferTypes(ClassHierarchyBase hierarchy) {
|
||||
inferFormalTypes(hierarchy);
|
||||
}
|
||||
|
||||
@override
|
||||
void inferFormalTypes(ClassHierarchyBase hierarchy) {
|
||||
if (_hasFormalsInferred) return;
|
||||
if (formals != null) {
|
||||
libraryBuilder.loader.withUriForCrashReporting(fileUri, charOffset, () {
|
||||
for (FormalParameterBuilder formal in formals!) {
|
||||
if (formal.type is InferableTypeBuilder) {
|
||||
if (formal.isInitializingFormal) {
|
||||
formal.finalizeInitializingFormal(classBuilder, hierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_hasSuperInitializingFormals) {
|
||||
List<Initializer>? initializers;
|
||||
if (beginInitializers != null) {
|
||||
BodyBuilder bodyBuilder = libraryBuilder.loader
|
||||
.createBodyBuilderForOutlineExpression(libraryBuilder,
|
||||
classBuilder, this, classBuilder.scope, fileUri);
|
||||
if (isConst) {
|
||||
bodyBuilder.constantContext = ConstantContext.required;
|
||||
}
|
||||
initializers = bodyBuilder.parseInitializers(beginInitializers!,
|
||||
doFinishConstructor: false);
|
||||
}
|
||||
finalizeSuperInitializingFormals(
|
||||
hierarchy, _superParameterDefaultValueCloners, initializers);
|
||||
}
|
||||
});
|
||||
}
|
||||
_hasFormalsInferred = true;
|
||||
}
|
||||
|
||||
ConstructorBuilder? _computeSuperTargetBuilder(
|
||||
List<Initializer>? initializers) {
|
||||
Constructor superTarget;
|
||||
Member superTarget;
|
||||
ClassBuilder superclassBuilder;
|
||||
|
||||
TypeBuilder? supertype = classBuilder.supertypeBuilder;
|
||||
|
@ -379,7 +539,7 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
MemberBuilder? memberBuilder = superclassBuilder.constructorScope
|
||||
.lookup("", charOffset, libraryBuilder.fileUri);
|
||||
if (memberBuilder is ConstructorBuilder) {
|
||||
superTarget = memberBuilder.constructor;
|
||||
superTarget = memberBuilder.invokeTarget;
|
||||
} else {
|
||||
// The error in this case should be reported elsewhere.
|
||||
return null;
|
||||
|
@ -392,6 +552,30 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
return constructorBuilder is ConstructorBuilder ? constructorBuilder : null;
|
||||
}
|
||||
|
||||
final bool _hasSuperInitializingFormals;
|
||||
|
||||
final List<DelayedDefaultValueCloner> _superParameterDefaultValueCloners =
|
||||
<DelayedDefaultValueCloner>[];
|
||||
|
||||
@override
|
||||
void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {
|
||||
if (_hasSuperInitializingFormals) {
|
||||
List<Initializer>? initializers;
|
||||
if (beginInitializers != null) {
|
||||
BodyBuilder bodyBuilder = libraryBuilder.loader
|
||||
.createBodyBuilderForOutlineExpression(libraryBuilder,
|
||||
declarationBuilder, this, declarationBuilder.scope, fileUri);
|
||||
if (isConst) {
|
||||
bodyBuilder.constantContext = ConstantContext.required;
|
||||
}
|
||||
initializers = bodyBuilder.parseInitializers(beginInitializers!,
|
||||
doFinishConstructor: false);
|
||||
}
|
||||
finalizeSuperInitializingFormals(
|
||||
hierarchy, _superParameterDefaultValueCloners, initializers);
|
||||
}
|
||||
}
|
||||
|
||||
void finalizeSuperInitializingFormals(
|
||||
ClassHierarchyBase hierarchy,
|
||||
List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
|
||||
|
@ -417,10 +601,10 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
superTargetBuilder.inferFormalTypes(hierarchy);
|
||||
}
|
||||
|
||||
Constructor superTarget;
|
||||
Member superTarget;
|
||||
FunctionNode? superConstructorFunction;
|
||||
if (superTargetBuilder != null) {
|
||||
superTarget = superTargetBuilder.constructor;
|
||||
superTarget = superTargetBuilder.invokeTarget;
|
||||
superConstructorFunction = superTargetBuilder.function;
|
||||
} else {
|
||||
// The error in this case should be reported elsewhere. Here we perform a
|
||||
|
@ -450,7 +634,7 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
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(
|
||||
|
@ -553,7 +737,7 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
// We're going to fully build the constructor so we need scopes.
|
||||
formalParameterScope = computeFormalParameterInitializerScope(
|
||||
computeFormalParameterScope(
|
||||
computeTypeParameterScope(declarationBuilder!.scope)));
|
||||
computeTypeParameterScope(declarationBuilder.scope)));
|
||||
} else {
|
||||
formalParameterScope = null;
|
||||
}
|
||||
|
@ -583,10 +767,7 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
|
||||
ConstructorBuilder? superTargetBuilder =
|
||||
_computeSuperTargetBuilder(constructor.initializers);
|
||||
if (superTargetBuilder is DeclaredSourceConstructorBuilder) {
|
||||
superTargetBuilder
|
||||
.addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
|
||||
} else if (superTargetBuilder is SyntheticSourceConstructorBuilder) {
|
||||
if (superTargetBuilder is SourceConstructorBuilder) {
|
||||
superTargetBuilder
|
||||
.addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
|
||||
}
|
||||
|
@ -608,137 +789,16 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
new TypeParameterType.withDefaultNullabilityForLibrary(
|
||||
typeParameter, libraryBuilder.library));
|
||||
}
|
||||
DartType type = new InterfaceType(
|
||||
InterfaceType type = new InterfaceType(
|
||||
enclosingClass, libraryBuilder.nonNullable, typeParameterTypes);
|
||||
returnType.registerInferredType(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Constructor get constructor => isPatch ? origin.constructor : _constructor;
|
||||
|
||||
@override
|
||||
Member get member => constructor;
|
||||
|
||||
void injectInvalidInitializer(Message message, int charOffset, int length,
|
||||
ExpressionGeneratorHelper helper) {
|
||||
List<Initializer> initializers = _constructor.initializers;
|
||||
Initializer lastInitializer = initializers.removeLast();
|
||||
assert(lastInitializer == superInitializer ||
|
||||
lastInitializer == redirectingInitializer);
|
||||
Initializer error = helper.buildInvalidInitializer(
|
||||
helper.buildProblem(message, charOffset, length));
|
||||
initializers.add(error..parent = _constructor);
|
||||
initializers.add(lastInitializer);
|
||||
}
|
||||
|
||||
void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
|
||||
{required InitializerInferenceResult? inferenceResult}) {
|
||||
List<Initializer> initializers = _constructor.initializers;
|
||||
if (initializer is SuperInitializer) {
|
||||
if (superInitializer != null) {
|
||||
injectInvalidInitializer(messageMoreThanOneSuperInitializer,
|
||||
initializer.fileOffset, "super".length, helper);
|
||||
} else if (redirectingInitializer != null) {
|
||||
injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithSuperInitializer,
|
||||
initializer.fileOffset,
|
||||
"super".length,
|
||||
helper);
|
||||
} else {
|
||||
inferenceResult?.applyResult(initializers, _constructor);
|
||||
superInitializer = initializer;
|
||||
|
||||
LocatedMessage? message = helper.checkArgumentsForFunction(
|
||||
initializer.target.function,
|
||||
initializer.arguments,
|
||||
initializer.arguments.fileOffset, <TypeParameter>[]);
|
||||
if (message != null) {
|
||||
initializers.add(helper.buildInvalidInitializer(
|
||||
helper.buildUnresolvedError(
|
||||
helper.constructorNameForDiagnostics(
|
||||
initializer.target.name.text),
|
||||
initializer.fileOffset,
|
||||
arguments: initializer.arguments,
|
||||
isSuper: true,
|
||||
message: message,
|
||||
kind: UnresolvedKind.Constructor))
|
||||
..parent = _constructor);
|
||||
} else {
|
||||
initializers.add(initializer..parent = _constructor);
|
||||
}
|
||||
}
|
||||
} else if (initializer is RedirectingInitializer) {
|
||||
if (superInitializer != null) {
|
||||
// Point to the existing super initializer.
|
||||
injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithSuperInitializer,
|
||||
superInitializer!.fileOffset,
|
||||
"super".length,
|
||||
helper);
|
||||
} else if (redirectingInitializer != null) {
|
||||
injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithMultipleRedirectInitializers,
|
||||
initializer.fileOffset,
|
||||
noLength,
|
||||
helper);
|
||||
} else if (initializers.isNotEmpty) {
|
||||
// Error on all previous ones.
|
||||
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(
|
||||
helper.buildProblem(
|
||||
messageRedirectingConstructorWithAnotherInitializer,
|
||||
initializer.fileOffset,
|
||||
length));
|
||||
error.parent = _constructor;
|
||||
initializers[i] = error;
|
||||
}
|
||||
inferenceResult?.applyResult(initializers, _constructor);
|
||||
initializers.add(initializer..parent = _constructor);
|
||||
redirectingInitializer = initializer;
|
||||
} else {
|
||||
inferenceResult?.applyResult(initializers, _constructor);
|
||||
redirectingInitializer = initializer;
|
||||
|
||||
LocatedMessage? message = helper.checkArgumentsForFunction(
|
||||
initializer.target.function,
|
||||
initializer.arguments,
|
||||
initializer.arguments.fileOffset, const <TypeParameter>[]);
|
||||
if (message != null) {
|
||||
initializers.add(helper.buildInvalidInitializer(
|
||||
helper.buildUnresolvedError(
|
||||
helper.constructorNameForDiagnostics(
|
||||
initializer.target.name.text,
|
||||
isSuper: false),
|
||||
initializer.fileOffset,
|
||||
arguments: initializer.arguments,
|
||||
isSuper: false,
|
||||
message: message,
|
||||
kind: UnresolvedKind.Constructor))
|
||||
..parent = _constructor);
|
||||
} else {
|
||||
initializers.add(initializer..parent = _constructor);
|
||||
}
|
||||
}
|
||||
} else if (redirectingInitializer != null) {
|
||||
int length = noLength;
|
||||
if (initializer is AssertInitializer) length = "assert".length;
|
||||
injectInvalidInitializer(
|
||||
messageRedirectingConstructorWithAnotherInitializer,
|
||||
initializer.fileOffset,
|
||||
length,
|
||||
helper);
|
||||
} else if (superInitializer != null) {
|
||||
injectInvalidInitializer(messageSuperInitializerNotLast,
|
||||
initializer.fileOffset, noLength, helper);
|
||||
} else {
|
||||
inferenceResult?.applyResult(initializers, _constructor);
|
||||
initializers.add(initializer..parent = _constructor);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
VariableDeclaration? getTearOffParameter(int index) {
|
||||
if (_constructorTearOff != null) {
|
||||
|
@ -802,17 +862,8 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
_constructor.initializers = [];
|
||||
redirectingInitializer = null;
|
||||
superInitializer = null;
|
||||
hasMovedSuperInitializer = false;
|
||||
}
|
||||
|
||||
@override
|
||||
List<ClassMember> get localMembers =>
|
||||
throw new UnsupportedError('${runtimeType}.localMembers');
|
||||
|
||||
@override
|
||||
List<ClassMember> get localSetters =>
|
||||
throw new UnsupportedError('${runtimeType}.localSetters');
|
||||
|
||||
/// Registers field as being initialized by this constructor.
|
||||
///
|
||||
/// The field can be initialized either via an initializing formal or via an
|
||||
|
@ -844,14 +895,10 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void checkVariance(
|
||||
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {}
|
||||
|
||||
@override
|
||||
void checkTypes(
|
||||
SourceLibraryBuilder library, TypeEnvironment typeEnvironment) {
|
||||
library.checkTypesInConstructorBuilder(this, typeEnvironment);
|
||||
super.checkTypes(library, typeEnvironment);
|
||||
List<DeclaredSourceConstructorBuilder>? patches = _patches;
|
||||
if (patches != null) {
|
||||
for (DeclaredSourceConstructorBuilder patch in patches) {
|
||||
|
@ -890,6 +937,9 @@ class SyntheticSourceConstructorBuilder extends DillConstructorBuilder
|
|||
SourceLibraryBuilder get libraryBuilder =>
|
||||
super.libraryBuilder as SourceLibraryBuilder;
|
||||
|
||||
@override
|
||||
DeclarationBuilder get declarationBuilder => classBuilder!;
|
||||
|
||||
@override
|
||||
bool get isRedirecting {
|
||||
for (Initializer initializer in constructor.initializers) {
|
||||
|
@ -972,3 +1022,150 @@ class SyntheticSourceConstructorBuilder extends DillConstructorBuilder
|
|||
void checkTypes(
|
||||
SourceLibraryBuilder library, TypeEnvironment typeEnvironment) {}
|
||||
}
|
||||
|
||||
class SourceViewConstructorBuilder extends AbstractSourceConstructorBuilder {
|
||||
late final Procedure _constructor;
|
||||
late final Procedure? _constructorTearOff;
|
||||
|
||||
@override
|
||||
final List<Initializer> initializers = [];
|
||||
|
||||
SourceViewConstructorBuilder(
|
||||
List<MetadataBuilder>? metadata,
|
||||
int modifiers,
|
||||
OmittedTypeBuilder returnType,
|
||||
String name,
|
||||
List<TypeVariableBuilder>? typeVariables,
|
||||
List<FormalParameterBuilder>? formals,
|
||||
SourceLibraryBuilder compilationUnit,
|
||||
int startCharOffset,
|
||||
int charOffset,
|
||||
int charOpenParenOffset,
|
||||
int charEndOffset,
|
||||
Reference? constructorReference,
|
||||
Reference? tearOffReference,
|
||||
NameScheme nameScheme,
|
||||
{String? nativeMethodName,
|
||||
required bool forAbstractClassOrEnum})
|
||||
: super(
|
||||
metadata,
|
||||
modifiers,
|
||||
returnType,
|
||||
name,
|
||||
typeVariables,
|
||||
formals,
|
||||
compilationUnit,
|
||||
charOffset,
|
||||
charOpenParenOffset,
|
||||
nativeMethodName) {
|
||||
_constructor = new Procedure(
|
||||
dummyName, ProcedureKind.Method, new FunctionNode(null),
|
||||
fileUri: compilationUnit.fileUri, reference: constructorReference)
|
||||
..fileOffset = charOffset
|
||||
..fileEndOffset = charEndOffset
|
||||
..isNonNullableByDefault = compilationUnit.isNonNullableByDefault;
|
||||
nameScheme
|
||||
.getConstructorMemberName(name, isTearOff: false)
|
||||
.attachMember(_constructor);
|
||||
_constructorTearOff = createConstructorTearOffProcedure(
|
||||
name,
|
||||
compilationUnit, compilationUnit.fileUri, charOffset, tearOffReference,
|
||||
forAbstractClassOrEnum: forAbstractClassOrEnum,
|
||||
// TODO(johnniwinther): Generate tear-off.
|
||||
/*forceCreateLowering: true*/
|
||||
);
|
||||
if (_constructorTearOff != null) {
|
||||
nameScheme
|
||||
.getConstructorMemberName(name, isTearOff: true)
|
||||
.attachMember(_constructorTearOff!);
|
||||
}
|
||||
}
|
||||
|
||||
SourceViewBuilder get viewBuilder => parent as SourceViewBuilder;
|
||||
|
||||
@override
|
||||
Member get member => _constructor;
|
||||
|
||||
@override
|
||||
Member get readTarget => _constructorTearOff ?? _constructor;
|
||||
|
||||
@override
|
||||
Member? get writeTarget => null;
|
||||
|
||||
@override
|
||||
Member get invokeTarget => _constructor;
|
||||
|
||||
@override
|
||||
FunctionNode get function => _constructor.function;
|
||||
|
||||
@override
|
||||
Iterable<Member> get exportedMembers => [_constructor];
|
||||
|
||||
@override
|
||||
void addSuperParameterDefaultValueCloners(
|
||||
List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {}
|
||||
|
||||
@override
|
||||
void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {}
|
||||
|
||||
@override
|
||||
int buildBodyNodes(void Function(Member, BuiltMemberKind) f) {
|
||||
// TODO(johnniwinther): Support augmentation.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
void buildOutlineNodes(void Function(Member, BuiltMemberKind) f) {
|
||||
_build();
|
||||
f(_constructor, BuiltMemberKind.ViewConstructor);
|
||||
if (_constructorTearOff != null) {
|
||||
f(_constructorTearOff!, BuiltMemberKind.Method);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
View view = viewBuilder.view;
|
||||
List<DartType> typeParameterTypes = <DartType>[];
|
||||
for (int i = 0; i < view.typeParameters.length; i++) {
|
||||
TypeParameter typeParameter = view.typeParameters[i];
|
||||
typeParameterTypes.add(
|
||||
new TypeParameterType.withDefaultNullabilityForLibrary(
|
||||
typeParameter, libraryBuilder.library));
|
||||
}
|
||||
ViewType type =
|
||||
new ViewType(view, libraryBuilder.nonNullable, typeParameterTypes);
|
||||
returnType.registerInferredType(type);
|
||||
}
|
||||
|
||||
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) {
|
||||
buildConstructorTearOffProcedure(
|
||||
tearOff: _constructorTearOff!,
|
||||
declarationConstructor: _constructor,
|
||||
implementationConstructor: _constructor,
|
||||
enclosingDeclarationTypeParameters: viewBuilder.view.typeParameters,
|
||||
libraryBuilder: libraryBuilder);
|
||||
}
|
||||
|
||||
_hasBeenBuilt = true;
|
||||
}
|
||||
_buildFormals(_constructor);
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Generate initializers and return statement.
|
||||
}
|
||||
|
|
|
@ -334,6 +334,11 @@ class SourceEnumBuilder extends SourceClassBuilder {
|
|||
charEndOffset,
|
||||
constructorReference,
|
||||
tearOffReference,
|
||||
new NameScheme(
|
||||
isInstanceMember: false,
|
||||
containerName: new ClassName(name),
|
||||
containerType: ContainerType.Class,
|
||||
libraryName: libraryName),
|
||||
forAbstractClassOrEnum: true);
|
||||
synthesizedDefaultConstructorBuilder
|
||||
.registerInitializedField(valuesBuilder);
|
||||
|
@ -762,7 +767,7 @@ class SourceEnumBuilder extends SourceClassBuilder {
|
|||
}
|
||||
} else {
|
||||
Expression initializer = bodyBuilder.buildStaticInvocation(
|
||||
constructorBuilder.constructor, arguments,
|
||||
constructorBuilder.invokeTarget, arguments,
|
||||
constness: Constness.explicitConst,
|
||||
charOffset: fieldBuilder.charOffset);
|
||||
ExpressionInferenceResult inferenceResult = bodyBuilder.typeInferrer
|
||||
|
@ -796,7 +801,7 @@ class SourceEnumBuilder extends SourceClassBuilder {
|
|||
}
|
||||
} else {
|
||||
Expression initializer = new ConstructorInvocation(
|
||||
constructorBuilder.constructor, arguments,
|
||||
constructorBuilder.invokeTarget as Constructor, arguments,
|
||||
isConst: true)
|
||||
..fileOffset = fieldBuilder.charOffset;
|
||||
if (!fieldBuilder.hasBodyBeenBuilt) {
|
||||
|
|
|
@ -122,6 +122,7 @@ class SourceExtensionBuilder extends ExtensionBuilderImpl
|
|||
case BuiltMemberKind.RedirectingFactory:
|
||||
case BuiltMemberKind.Field:
|
||||
case BuiltMemberKind.Method:
|
||||
case BuiltMemberKind.ViewConstructor:
|
||||
case BuiltMemberKind.ViewMethod:
|
||||
case BuiltMemberKind.ViewGetter:
|
||||
case BuiltMemberKind.ViewSetter:
|
||||
|
|
|
@ -90,6 +90,7 @@ class SourceFactoryBuilder extends SourceFunctionBuilderImpl {
|
|||
.attachMember(_procedureInternal);
|
||||
_factoryTearOff = createFactoryTearOffProcedure(name, libraryBuilder,
|
||||
libraryBuilder.fileUri, charOffset, tearOffReference);
|
||||
// TODO(johnniwinther): Use [NameScheme] for constructor tear-off names.
|
||||
this.asyncModifier = asyncModifier;
|
||||
}
|
||||
|
||||
|
@ -166,7 +167,6 @@ class SourceFactoryBuilder extends SourceFunctionBuilderImpl {
|
|||
tearOff: _factoryTearOff!,
|
||||
declarationConstructor: _procedure,
|
||||
implementationConstructor: _procedureInternal,
|
||||
enclosingClass: classBuilder.cls,
|
||||
libraryBuilder: libraryBuilder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2187,12 +2187,14 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
Map<String, MemberBuilder> constructors = declaration.constructors!;
|
||||
Map<String, MemberBuilder> setters = declaration.setters!;
|
||||
|
||||
Scope classScope = new Scope(
|
||||
Scope memberScope = new Scope(
|
||||
local: members,
|
||||
setters: setters,
|
||||
parent: scope.withTypeVariables(typeVariables),
|
||||
debugName: "extension $name",
|
||||
debugName: "view $name",
|
||||
isModifiable: false);
|
||||
ConstructorScope constructorScope =
|
||||
new ConstructorScope(name, constructors);
|
||||
|
||||
View? referenceFrom = referencesFromIndexed?.lookupView(name);
|
||||
|
||||
|
@ -2215,7 +2217,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
modifiers,
|
||||
declaration.name,
|
||||
typeVariables,
|
||||
classScope,
|
||||
memberScope,
|
||||
constructorScope,
|
||||
this,
|
||||
startOffset,
|
||||
nameOffset,
|
||||
|
@ -2732,8 +2735,22 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
constructorTearOffName(constructorName),
|
||||
_currentClassReferencesFromIndexed!.library));
|
||||
}
|
||||
DeclaredSourceConstructorBuilder constructorBuilder =
|
||||
new DeclaredSourceConstructorBuilder(
|
||||
AbstractSourceConstructorBuilder constructorBuilder;
|
||||
|
||||
ContainerType containerType =
|
||||
currentTypeParameterScopeBuilder.containerType;
|
||||
ContainerName? containerName =
|
||||
currentTypeParameterScopeBuilder.containerName;
|
||||
NameScheme nameScheme = new NameScheme(
|
||||
isInstanceMember: false,
|
||||
containerName: containerName,
|
||||
containerType: containerType,
|
||||
libraryName: referencesFrom != null
|
||||
? new LibraryName(referencesFrom!.reference)
|
||||
: libraryName);
|
||||
if (currentTypeParameterScopeBuilder.kind ==
|
||||
TypeParameterScopeKind.viewDeclaration) {
|
||||
constructorBuilder = new SourceViewConstructorBuilder(
|
||||
metadata,
|
||||
modifiers & ~abstractMask,
|
||||
addInferableType(),
|
||||
|
@ -2747,8 +2764,28 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
charEndOffset,
|
||||
constructorReference,
|
||||
tearOffReference,
|
||||
nameScheme,
|
||||
nativeMethodName: nativeMethodName,
|
||||
forAbstractClassOrEnum: forAbstractClass);
|
||||
} else {
|
||||
constructorBuilder = new DeclaredSourceConstructorBuilder(
|
||||
metadata,
|
||||
modifiers & ~abstractMask,
|
||||
addInferableType(),
|
||||
constructorName,
|
||||
typeVariables,
|
||||
formals,
|
||||
this,
|
||||
startCharOffset,
|
||||
charOffset,
|
||||
charOpenParenOffset,
|
||||
charEndOffset,
|
||||
constructorReference,
|
||||
tearOffReference,
|
||||
nameScheme,
|
||||
nativeMethodName: nativeMethodName,
|
||||
forAbstractClassOrEnum: forAbstractClass);
|
||||
}
|
||||
checkTypeVariables(typeVariables, constructorBuilder);
|
||||
// TODO(johnniwinther): There is no way to pass the tear off reference here.
|
||||
addBuilder(constructorName, constructorBuilder, charOffset,
|
||||
|
@ -3920,6 +3957,54 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
inErrorRecovery: issues.isNotEmpty);
|
||||
}
|
||||
|
||||
void processSourceFieldBuilder(SourceFieldBuilder member) {
|
||||
TypeBuilder? fieldType = member.type;
|
||||
if (fieldType is! OmittedTypeBuilder) {
|
||||
List<NonSimplicityIssue> issues =
|
||||
getInboundReferenceIssuesInType(fieldType);
|
||||
reportIssues(issues);
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(fieldType);
|
||||
}
|
||||
}
|
||||
|
||||
void processSourceConstructorBuilder(SourceMemberBuilder member,
|
||||
{required bool inErrorRecovery}) {
|
||||
List<FormalParameterBuilder>? formals;
|
||||
if (member is SourceFactoryBuilder) {
|
||||
assert(member.isFactory,
|
||||
"Unexpected constructor member (${member.runtimeType}).");
|
||||
count += computeDefaultTypesForVariables(member.typeVariables,
|
||||
// Type variables are inherited from the class so if the class
|
||||
// has issues, so does the factory constructors.
|
||||
inErrorRecovery: inErrorRecovery);
|
||||
formals = member.formals;
|
||||
} else {
|
||||
assert(member is AbstractSourceConstructorBuilder,
|
||||
"Unexpected constructor member (${member.runtimeType}).");
|
||||
formals = (member as AbstractSourceConstructorBuilder).formals;
|
||||
}
|
||||
if (formals != null && formals.isNotEmpty) {
|
||||
for (FormalParameterBuilder formal in formals) {
|
||||
List<NonSimplicityIssue> issues =
|
||||
getInboundReferenceIssuesInType(formal.type);
|
||||
reportIssues(issues);
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(formal.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void processSourceMemberBuilder(SourceMemberBuilder member,
|
||||
{required bool inErrorRecovery}) {
|
||||
if (member is SourceProcedureBuilder) {
|
||||
processSourceProcedureBuilder(member);
|
||||
} else if (member is SourceFieldBuilder) {
|
||||
processSourceFieldBuilder(member);
|
||||
} else {
|
||||
processSourceConstructorBuilder(member,
|
||||
inErrorRecovery: inErrorRecovery);
|
||||
}
|
||||
}
|
||||
|
||||
void computeDefaultValuesForDeclaration(Builder declaration) {
|
||||
if (declaration is SourceClassBuilder) {
|
||||
List<NonSimplicityIssue> issues = getNonSimplicityIssuesForDeclaration(
|
||||
|
@ -3929,51 +4014,23 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
count += computeDefaultTypesForVariables(declaration.typeVariables,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
|
||||
Iterator<MemberBuilder> iterator = declaration.constructorScope
|
||||
.filteredIterator(
|
||||
Iterator<SourceMemberBuilder> iterator = declaration.constructorScope
|
||||
.filteredIterator<SourceMemberBuilder>(
|
||||
includeDuplicates: false, includeAugmentations: true);
|
||||
while (iterator.moveNext()) {
|
||||
MemberBuilder member = iterator.current;
|
||||
List<FormalParameterBuilder>? formals;
|
||||
if (member is SourceFactoryBuilder) {
|
||||
assert(member.isFactory,
|
||||
"Unexpected constructor member (${member.runtimeType}).");
|
||||
count += computeDefaultTypesForVariables(member.typeVariables,
|
||||
// Type variables are inherited from the class so if the class
|
||||
// has issues, so does the factory constructors.
|
||||
processSourceMemberBuilder(iterator.current,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
formals = member.formals;
|
||||
} else {
|
||||
assert(member is DeclaredSourceConstructorBuilder,
|
||||
"Unexpected constructor member (${member.runtimeType}).");
|
||||
formals = (member as DeclaredSourceConstructorBuilder).formals;
|
||||
}
|
||||
if (formals != null && formals.isNotEmpty) {
|
||||
for (FormalParameterBuilder formal in formals) {
|
||||
List<NonSimplicityIssue> issues =
|
||||
getInboundReferenceIssuesInType(formal.type);
|
||||
reportIssues(issues);
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(
|
||||
formal.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<Builder> memberIterator = declaration.fullMemberIterator;
|
||||
while (memberIterator.moveNext()) {
|
||||
Builder member = memberIterator.current;
|
||||
if (member is SourceProcedureBuilder) {
|
||||
processSourceProcedureBuilder(member);
|
||||
if (member is SourceMemberBuilder) {
|
||||
processSourceMemberBuilder(member,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
} else {
|
||||
assert(member is SourceFieldBuilder,
|
||||
assert(false,
|
||||
"Unexpected class member $member (${member.runtimeType}).");
|
||||
TypeBuilder? fieldType = (member as SourceFieldBuilder).type;
|
||||
if (fieldType is! OmittedTypeBuilder) {
|
||||
List<NonSimplicityIssue> issues =
|
||||
getInboundReferenceIssuesInType(fieldType);
|
||||
reportIssues(issues);
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(fieldType);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (declaration is SourceTypeAliasBuilder) {
|
||||
|
@ -3985,24 +4042,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
count += computeDefaultTypesForVariables(declaration.typeVariables,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(declaration.type);
|
||||
} else if (declaration is SourceFunctionBuilder) {
|
||||
List<NonSimplicityIssue> issues =
|
||||
getNonSimplicityIssuesForTypeVariables(declaration.typeVariables);
|
||||
if (declaration.formals != null && declaration.formals!.isNotEmpty) {
|
||||
for (FormalParameterBuilder formal in declaration.formals!) {
|
||||
issues.addAll(getInboundReferenceIssuesInType(formal.type));
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(formal.type);
|
||||
}
|
||||
}
|
||||
if (declaration.returnType is! OmittedTypeBuilder) {
|
||||
issues
|
||||
.addAll(getInboundReferenceIssuesInType(declaration.returnType));
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(
|
||||
declaration.returnType);
|
||||
}
|
||||
reportIssues(issues);
|
||||
count += computeDefaultTypesForVariables(declaration.typeVariables,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
} else if (declaration is SourceMemberBuilder) {
|
||||
processSourceMemberBuilder(declaration, inErrorRecovery: false);
|
||||
} else if (declaration is SourceExtensionBuilder) {
|
||||
List<NonSimplicityIssue> issues = getNonSimplicityIssuesForDeclaration(
|
||||
declaration,
|
||||
|
@ -4012,15 +4053,11 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
inErrorRecovery: issues.isNotEmpty);
|
||||
|
||||
declaration.forEach((String name, Builder member) {
|
||||
if (member is SourceProcedureBuilder) {
|
||||
processSourceProcedureBuilder(member);
|
||||
} else if (member is SourceFieldBuilder) {
|
||||
if (member.type is! OmittedTypeBuilder) {
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(
|
||||
member.type);
|
||||
}
|
||||
if (member is SourceMemberBuilder) {
|
||||
processSourceMemberBuilder(member,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
} else {
|
||||
throw new StateError(
|
||||
assert(false,
|
||||
"Unexpected extension member $member (${member.runtimeType}).");
|
||||
}
|
||||
});
|
||||
|
@ -4033,26 +4070,14 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
inErrorRecovery: issues.isNotEmpty);
|
||||
|
||||
declaration.forEach((String name, Builder member) {
|
||||
if (member is SourceProcedureBuilder) {
|
||||
processSourceProcedureBuilder(member);
|
||||
} else if (member is SourceFieldBuilder) {
|
||||
if (member.type is! OmittedTypeBuilder) {
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(
|
||||
member.type);
|
||||
}
|
||||
if (member is SourceMemberBuilder) {
|
||||
processSourceMemberBuilder(member,
|
||||
inErrorRecovery: issues.isNotEmpty);
|
||||
} else {
|
||||
throw new StateError(
|
||||
"Unexpected extension member $member (${member.runtimeType}).");
|
||||
assert(false,
|
||||
"Unexpected view member $member (${member.runtimeType}).");
|
||||
}
|
||||
});
|
||||
} else if (declaration is SourceFieldBuilder) {
|
||||
if (declaration.type is! OmittedTypeBuilder) {
|
||||
List<NonSimplicityIssue> issues =
|
||||
getInboundReferenceIssuesInType(declaration.type);
|
||||
reportIssues(issues);
|
||||
_recursivelyReportGenericFunctionTypesAsBoundsForType(
|
||||
declaration.type);
|
||||
}
|
||||
} else {
|
||||
assert(
|
||||
declaration is PrefixBuilder ||
|
||||
|
@ -4339,10 +4364,11 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
|
|||
}
|
||||
|
||||
void checkTypesInConstructorBuilder(
|
||||
DeclaredSourceConstructorBuilder constructorBuilder,
|
||||
SourceConstructorBuilder constructorBuilder,
|
||||
List<FormalParameterBuilder>? formals,
|
||||
TypeEnvironment typeEnvironment) {
|
||||
if (!constructorBuilder.isExternal && constructorBuilder.formals != null) {
|
||||
checkInitializersInFormals(constructorBuilder.formals!, typeEnvironment);
|
||||
if (!constructorBuilder.isExternal && formals != null) {
|
||||
checkInitializersInFormals(formals, typeEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1005,8 +1005,8 @@ severity: $severity
|
|||
}
|
||||
|
||||
void registerConstructorToBeInferred(
|
||||
Constructor constructor, SourceConstructorBuilder builder) {
|
||||
_typeInferenceEngine!.toBeInferred[constructor] = builder;
|
||||
Member member, SourceConstructorBuilder builder) {
|
||||
_typeInferenceEngine!.toBeInferred[member] = builder;
|
||||
}
|
||||
|
||||
void registerTypeDependency(Member member, TypeDependency typeDependency) {
|
||||
|
|
|
@ -178,6 +178,7 @@ enum BuiltMemberKind {
|
|||
ExtensionSetter,
|
||||
ExtensionOperator,
|
||||
ExtensionTearOff,
|
||||
ViewConstructor,
|
||||
ViewMethod,
|
||||
ViewGetter,
|
||||
ViewSetter,
|
||||
|
|
|
@ -43,6 +43,7 @@ class SourceViewBuilder extends ViewBuilderImpl
|
|||
String name,
|
||||
this.typeParameters,
|
||||
Scope scope,
|
||||
ConstructorScope constructorScope,
|
||||
SourceLibraryBuilder parent,
|
||||
int startOffset,
|
||||
int nameOffset,
|
||||
|
@ -56,7 +57,8 @@ class SourceViewBuilder extends ViewBuilderImpl
|
|||
TypeVariableBuilder.typeParametersFromBuilders(typeParameters),
|
||||
reference: referenceFrom?.reference)
|
||||
..fileOffset = nameOffset,
|
||||
super(metadata, modifiers, name, parent, nameOffset, scope);
|
||||
super(metadata, modifiers, name, parent, nameOffset, scope,
|
||||
constructorScope);
|
||||
|
||||
@override
|
||||
SourceLibraryBuilder get libraryBuilder =>
|
||||
|
@ -125,6 +127,9 @@ class SourceViewBuilder extends ViewBuilderImpl
|
|||
case BuiltMemberKind.LateIsSetField:
|
||||
kind = ViewMemberKind.Field;
|
||||
break;
|
||||
case BuiltMemberKind.ViewConstructor:
|
||||
kind = ViewMemberKind.Constructor;
|
||||
break;
|
||||
case BuiltMemberKind.ViewMethod:
|
||||
kind = ViewMemberKind.Method;
|
||||
break;
|
||||
|
|
|
@ -338,20 +338,20 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
}
|
||||
|
||||
/// Ensures that all parameter types of [constructor] have been inferred.
|
||||
void _inferConstructorParameterTypes(Constructor target) {
|
||||
SourceConstructorBuilder? constructor = engine.beingInferred[target];
|
||||
if (constructor != null) {
|
||||
void _inferConstructorParameterTypes(Member target) {
|
||||
SourceConstructorBuilder? constructorBuilder = engine.beingInferred[target];
|
||||
if (constructorBuilder != null) {
|
||||
// There is a cyclic dependency where inferring the types of the
|
||||
// initializing formals of a constructor required us to infer the
|
||||
// corresponding field type which required us to know the type of the
|
||||
// constructor.
|
||||
String name = target.enclosingClass.name;
|
||||
String name = constructorBuilder.declarationBuilder.name;
|
||||
if (target.name.text.isNotEmpty) {
|
||||
// TODO(ahe): Use `inferrer.helper.constructorNameForDiagnostics`
|
||||
// instead. However, `inferrer.helper` may be null.
|
||||
name += ".${target.name.text}";
|
||||
}
|
||||
constructor.libraryBuilder.addProblem(
|
||||
constructorBuilder.libraryBuilder.addProblem(
|
||||
templateCantInferTypeDueToCircularity.withArguments(name),
|
||||
target.fileOffset,
|
||||
name.length,
|
||||
|
@ -365,10 +365,10 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
for (VariableDeclaration declaration in target.function.namedParameters) {
|
||||
declaration.type ??= const InvalidType();
|
||||
}*/
|
||||
} else if ((constructor = engine.toBeInferred[target]) != null) {
|
||||
} else if ((constructorBuilder = engine.toBeInferred[target]) != null) {
|
||||
engine.toBeInferred.remove(target);
|
||||
engine.beingInferred[target] = constructor!;
|
||||
constructor.inferFormalTypes(hierarchyBuilder);
|
||||
engine.beingInferred[target] = constructorBuilder!;
|
||||
constructorBuilder.inferFormalTypes(hierarchyBuilder);
|
||||
engine.beingInferred.remove(target);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,14 +155,14 @@ abstract class TypeInferenceEngine {
|
|||
/// This is represented as a map from a constructor to its library
|
||||
/// builder because the builder is used to report errors due to cyclic
|
||||
/// inference dependencies.
|
||||
final Map<Constructor, SourceConstructorBuilder> toBeInferred = {};
|
||||
final Map<Member, SourceConstructorBuilder> toBeInferred = {};
|
||||
|
||||
/// A map containing constructors in the process of being inferred.
|
||||
///
|
||||
/// This is used to detect cyclic inference dependencies. It is represented
|
||||
/// as a map from a constructor to its library builder because the builder
|
||||
/// is used to report errors.
|
||||
final Map<Constructor, SourceConstructorBuilder> beingInferred = {};
|
||||
final Map<Member, SourceConstructorBuilder> beingInferred = {};
|
||||
|
||||
final Map<Member, TypeDependency> typeDependencies = {};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ extension E on int {
|
|||
Function<Z extends A>() baz3() => throw 42;
|
||||
Function<Z extends A>() get baz4 => throw 42;
|
||||
void set baz5(Function<Z extends A>() a) {}
|
||||
static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
}
|
||||
|
||||
main() {}
|
||||
|
|
|
@ -23,6 +23,7 @@ extension E on int {
|
|||
Function<Z extends A>() baz3() => throw 42;
|
||||
Function<Z extends A>() get baz4 => throw 42;
|
||||
void set baz5(Function<Z extends A>() a) {}
|
||||
static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
}
|
||||
|
||||
main() {}
|
||||
|
|
|
@ -19,6 +19,7 @@ extension E on int {
|
|||
Function<Z extends A>() baz3() => throw 42;
|
||||
Function<Z extends A>() get baz4 => throw 42;
|
||||
baz2(Function<Z extends A>() a) {}
|
||||
static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
void set baz5(Function<Z extends A>() a) {}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,14 @@ library /*isNonNullableByDefault*/;
|
|||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:30:19: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
// ^
|
||||
// pkg/front_end/testcases/general/issue42435.dart:5:9: Context: Bound of this variable references variable 'X' from the same declaration.
|
||||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:29:26: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// void set baz5(Function<Z extends A>() a) {}
|
||||
|
@ -168,9 +176,11 @@ extension E on core::int {
|
|||
method baz3 = self::E|baz3;
|
||||
tearoff baz3 = self::E|get#baz3;
|
||||
get baz4 = self::E|get#baz4;
|
||||
static field baz6 = self::E|baz6;
|
||||
set baz5 = self::E|set#baz5;
|
||||
}
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic bar6 = let final Never #t2 = (() → Never => throw 42)(){() → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic E|baz6 = let final Never #t3 = (() → Never => throw 42)(){() → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
|
||||
static method bar2(<Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic a) → dynamic {}
|
||||
static method bar3() → <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic
|
||||
return throw 42;
|
||||
|
|
|
@ -122,6 +122,14 @@ library /*isNonNullableByDefault*/;
|
|||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:30:19: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
// ^
|
||||
// pkg/front_end/testcases/general/issue42435.dart:5:9: Context: Bound of this variable references variable 'X' from the same declaration.
|
||||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:29:26: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// void set baz5(Function<Z extends A>() a) {}
|
||||
|
@ -168,9 +176,11 @@ extension E on core::int {
|
|||
method baz3 = self::E|baz3;
|
||||
tearoff baz3 = self::E|get#baz3;
|
||||
get baz4 = self::E|get#baz4;
|
||||
static field baz6 = self::E|baz6;
|
||||
set baz5 = self::E|set#baz5;
|
||||
}
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic bar6 = let final Never #t2 = (() → Never => throw 42)(){() → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic E|baz6 = let final Never #t3 = (() → Never => throw 42)(){() → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
|
||||
static method bar2(<Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic a) → dynamic {}
|
||||
static method bar3() → <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic
|
||||
return throw 42;
|
||||
|
|
|
@ -122,6 +122,14 @@ library /*isNonNullableByDefault*/;
|
|||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:30:19: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
// ^
|
||||
// pkg/front_end/testcases/general/issue42435.dart:5:9: Context: Bound of this variable references variable 'X' from the same declaration.
|
||||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:29:26: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// void set baz5(Function<Z extends A>() a) {}
|
||||
|
@ -167,9 +175,11 @@ extension E on core::int {
|
|||
method baz3 = self::E|baz3;
|
||||
tearoff baz3 = self::E|get#baz3;
|
||||
get baz4 = self::E|get#baz4;
|
||||
static field baz6 = self::E|baz6;
|
||||
set baz5 = self::E|set#baz5;
|
||||
}
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic bar6;
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic E|baz6;
|
||||
static method bar2(<Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic a) → dynamic
|
||||
;
|
||||
static method bar3() → <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic
|
||||
|
|
|
@ -122,6 +122,14 @@ library /*isNonNullableByDefault*/;
|
|||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:30:19: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// static Function<Z extends A>() baz6 = (() => throw 42)();
|
||||
// ^
|
||||
// pkg/front_end/testcases/general/issue42435.dart:5:9: Context: Bound of this variable references variable 'X' from the same declaration.
|
||||
// class A<X extends A<X>> {}
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/issue42435.dart:29:26: Error: Generic type 'A' can't be used without type arguments in a type variable bound.
|
||||
// Try providing type arguments to 'A' here.
|
||||
// void set baz5(Function<Z extends A>() a) {}
|
||||
|
@ -168,9 +176,11 @@ extension E on core::int {
|
|||
method baz3 = self::E|baz3;
|
||||
tearoff baz3 = self::E|get#baz3;
|
||||
get baz4 = self::E|get#baz4;
|
||||
static field baz6 = self::E|baz6;
|
||||
set baz5 = self::E|set#baz5;
|
||||
}
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic bar6 = let final Never #t2 = (() → Never => throw 42)(){() → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
|
||||
static field <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic E|baz6 = let final Never #t3 = (() → Never => throw 42)(){() → Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
|
||||
static method bar2(<Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic a) → dynamic {}
|
||||
static method bar3() → <Z extends self::A<self::A<dynamic>> = dynamic>() → dynamic
|
||||
return throw 42;
|
||||
|
|
|
@ -215,6 +215,7 @@ variance/class_type_parameter_modifier: FormatterCrash
|
|||
variance/generic_covariance_sound_variance: FormatterCrash
|
||||
variance/mixin_type_parameter_modifier: FormatterCrash
|
||||
variance/unconstrained_inference: FormatterCrash
|
||||
views/constructors: FormatterCrash
|
||||
views/procedures: FormatterCrash
|
||||
views/representation: FormatterCrash
|
||||
views/view_class_declaration: FormatterCrash
|
||||
|
|
15
pkg/front_end/testcases/views/constructors.dart
Normal file
15
pkg/front_end/testcases/views/constructors.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) 2022, 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.
|
||||
|
||||
view class Class1 {
|
||||
final int field;
|
||||
|
||||
Class1(this.field);
|
||||
}
|
||||
|
||||
view class Class2 {
|
||||
final int field;
|
||||
|
||||
Class2(this.field);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
view Class1 /* representationType = core::int */ {
|
||||
constructor • = self::Class1|;
|
||||
}
|
||||
view Class2 /* representationType = core::int */ {
|
||||
constructor • = self::Class2|;
|
||||
}
|
||||
method Class1|(core::int field) → self::Class1
|
||||
;
|
||||
method Class2|(core::int field) → self::Class2
|
||||
;
|
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
view Class1 /* representationType = core::int */ {
|
||||
constructor • = self::Class1|;
|
||||
}
|
||||
view Class2 /* representationType = core::int */ {
|
||||
constructor • = self::Class2|;
|
||||
}
|
||||
method Class1|(core::int field) → self::Class1
|
||||
;
|
||||
method Class2|(core::int field) → self::Class2
|
||||
;
|
|
@ -0,0 +1,10 @@
|
|||
view
|
||||
class Class1 {
|
||||
final int field;
|
||||
Class1(this.field);
|
||||
}
|
||||
view
|
||||
class Class2 {
|
||||
final int field;
|
||||
Class2(this.field);
|
||||
}
|
14
pkg/front_end/testcases/views/constructors.dart.weak.expect
Normal file
14
pkg/front_end/testcases/views/constructors.dart.weak.expect
Normal file
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
view Class1 /* representationType = core::int */ {
|
||||
constructor • = self::Class1|;
|
||||
}
|
||||
view Class2 /* representationType = core::int */ {
|
||||
constructor • = self::Class2|;
|
||||
}
|
||||
method Class1|(core::int field) → self::Class1
|
||||
;
|
||||
method Class2|(core::int field) → self::Class2
|
||||
;
|
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
view Class1 /* representationType = core::int */ {
|
||||
constructor • = self::Class1|;
|
||||
}
|
||||
view Class2 /* representationType = core::int */ {
|
||||
constructor • = self::Class2|;
|
||||
}
|
||||
method Class1|(core::int field) → self::Class1
|
||||
;
|
||||
method Class2|(core::int field) → self::Class2
|
||||
;
|
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
view Class1 /* representationType = core::int */ {
|
||||
constructor • = self::Class1|;
|
||||
}
|
||||
view Class2 /* representationType = core::int */ {
|
||||
constructor • = self::Class2|;
|
||||
}
|
||||
method Class1|(core::int field) → self::Class1
|
||||
;
|
||||
method Class2|(core::int field) → self::Class2
|
||||
;
|
|
@ -0,0 +1,14 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
view Class1 /* representationType = core::int */ {
|
||||
constructor • = self::Class1|;
|
||||
}
|
||||
view Class2 /* representationType = core::int */ {
|
||||
constructor • = self::Class2|;
|
||||
}
|
||||
method Class1|(core::int field) → self::Class1
|
||||
;
|
||||
method Class2|(core::int field) → self::Class2
|
||||
;
|
Loading…
Reference in a new issue