diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart index e276dab6c0f..4ed0bd67b73 100644 --- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart +++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart @@ -245,10 +245,7 @@ class FormalParameterBuilder extends ModifierBuilderImpl } } - /// Builds the default value from this [initializerToken] if this is a - /// formal parameter on a const constructor or instance method. - void buildOutlineExpressions(SourceLibraryBuilder libraryBuilder, - List delayedActionPerformers) { + bool get needsDefaultValuesBuiltAsOutlineExpressions { // For modular compilation we need to include default values for optional // and named parameters in several cases: // * for const constructors to enable constant evaluation, @@ -256,15 +253,20 @@ class FormalParameterBuilder extends ModifierBuilderImpl // noSuchMethod forwarders, and // * for generative constructors to support forwarding constructors // in mixin applications. - bool needsDefaultValues = false; if (parent is ConstructorBuilder) { - needsDefaultValues = true; + return true; } else if (parent is SourceFactoryBuilder) { - needsDefaultValues = parent!.isFactory && parent!.isConst; + return parent!.isFactory && parent!.isConst; } else { - needsDefaultValues = parent!.isClassInstanceMember; + return parent!.isClassInstanceMember; } - if (needsDefaultValues) { + } + + /// Builds the default value from this [initializerToken] if this is a + /// formal parameter on a const constructor or instance method. + void buildOutlineExpressions(SourceLibraryBuilder libraryBuilder, + List delayedActionPerformers) { + if (needsDefaultValuesBuiltAsOutlineExpressions) { if (initializerToken != null) { final DeclarationBuilder declarationBuilder = parent!.parent as DeclarationBuilder; diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart index ebf7e9de7df..cc3d5f29e9e 100644 --- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart @@ -242,6 +242,62 @@ class BodyBuilder extends StackListenerImpl /// nominal correspondingly. bool _insideOfFormalParameterType = false; + /// True if the currently built part of the body is inside of a default value + /// of a formal parameter. + /// + /// Being inside of a default value is treated with regards to possible + /// nestedness of the default values. See the documentation on + /// [_defaultValueNestingLevel] for details. + bool get _insideOfFormalParameterDefaultValue { + return _defaultValueNestingLevel > 0; + } + + /// Numeric nestedness of formal parameter default values. + /// + /// The value of 0 means that the currently built part is not within a default + /// value. Consider the following clarifying examples. + /// + /// // `const Bar()` isn't within a default value. + /// foo() => const Bar(); + /// + /// // `const Bar()` is at [_defaultValueNestingLevel] = 1. + /// foo([dynamic x = const Bar()]) {} + /// + /// // `const Bar()` is at [_defaultValueNestingLevel] = 2. + /// // `const Baz()` is at [_defaultValueNestingLevel] = 1. + /// foo([dynamic x = ([dynamic y = const Bar()]) => const Baz()]) {} + /// + /// Since function expressions aren't const values, currently it's not + /// possible to write a program with [_defaultValueNestingLevel] > 1 that + /// doesn't contain a compile-time error. However, it's still necessary to + /// track the nestedness level to avoid bad compiler states and compiler + /// crashes. + int _defaultValueNestingLevel = 0; + + /// Returns true if newly created aliased or redirecting invocations need + /// post-processing such as resolution or unaliasing. + /// + /// The need for the condition computed by the getter is due to some parts of + /// the AST being built twice. The first time they are built is during + /// outline expressions building. The second time they are built during the + /// function body building. However, they are fully processed only the first + /// time they are built, and the second time around they are discarded. + /// Additional complication arises due to some nodes, such as annotations, + /// being built only once. So we only need to add the nodes created for the + /// first time into the lists of nodes for post-processing. + /// + /// The invocations inside default values that need resolution or unaliasing + /// were already added to the post-processing lists during outline expression + /// building. Only those invocations that are built outside of the default + /// values or inside the default values that aren't built as outline + /// expressions need to be added during the second pass. + bool get _createdStaticInvocationsNeedPostProcessing { + return _context.hasFormalParameters && + !_insideOfFormalParameterDefaultValue || + !_context.hasImmediateOutlineExpressionsBuilt || + !_context.needsImmediateValuesBuiltAsOutlineExpressions; + } + bool get inFunctionType => _structuralParameterDepthLevel > 0 || _insideOfFormalParameterType; @@ -306,6 +362,13 @@ class BodyBuilder extends StackListenerImpl final List delayedTypeAliasedFactoryInvocations = []; + /// List of type aliased constructor invocations delayed for resolution. + /// + /// A resolution of a type aliased constructor invocation can be delayed + /// because the inference in the declaration of the target isn't done yet. + final List + delayedTypeAliasedConstructorInvocations = []; + /// Variables with metadata. Their types need to be inferred late, for /// example, in [finishFunction]. List? variablesWithMetadata; @@ -1043,7 +1106,8 @@ class BodyBuilder extends StackListenerImpl {List? delayedActionPerformers, required bool allowFurtherDelays}) { _finishVariableMetadata(); - _unaliasTypeAliasedConstructorInvocations(); + _unaliasTypeAliasedConstructorInvocations( + typeAliasedConstructorInvocations); _unaliasTypeAliasedFactoryInvocations(typeAliasedFactoryInvocations); _resolveRedirectingFactoryTargets(redirectingFactoryInvocations, allowFurtherDelays: allowFurtherDelays); @@ -1052,7 +1116,11 @@ class BodyBuilder extends StackListenerImpl assert( delayedActionPerformers != null, "Body builder has delayed actions that cannot be performed: " - "$delayedRedirectingFactoryInvocations"); + "${[ + ...delayedRedirectingFactoryInvocations, + ...delayedTypeAliasedFactoryInvocations, + ...delayedTypeAliasedConstructorInvocations, + ]}"); delayedActionPerformers?.add(this); } } @@ -1565,34 +1633,41 @@ class BodyBuilder extends StackListenerImpl } } - void _unaliasTypeAliasedConstructorInvocations() { + void _unaliasTypeAliasedConstructorInvocations( + List + typeAliasedConstructorInvocations) { for (TypeAliasedConstructorInvocation invocation in typeAliasedConstructorInvocations) { - if (!invocation.hasBeenInferred) { - assert( - isOrphaned(invocation), "Node $invocation has not been inferred."); - continue; + assert(invocation.hasBeenInferred || isOrphaned(invocation), + "Node $invocation has not been inferred."); + + Expression? replacement; + if (invocation.hasBeenInferred) { + bool inferred = !hasExplicitTypeArguments(invocation.arguments); + DartType aliasedType = new TypedefType( + invocation.typeAliasBuilder.typedef, + Nullability.nonNullable, + invocation.arguments.types); + libraryBuilder.checkBoundsInType( + aliasedType, typeEnvironment, uri, invocation.fileOffset, + allowSuperBounded: false, inferred: inferred); + DartType unaliasedType = aliasedType.unalias; + List? invocationTypeArguments = null; + if (unaliasedType is InterfaceType) { + invocationTypeArguments = unaliasedType.typeArguments; + } + Arguments invocationArguments = forest.createArguments( + noLocation, invocation.arguments.positional, + types: invocationTypeArguments, named: invocation.arguments.named); + replacement = new ConstructorInvocation( + invocation.target, invocationArguments, + isConst: invocation.isConst); } - bool inferred = !hasExplicitTypeArguments(invocation.arguments); - DartType aliasedType = new TypedefType( - invocation.typeAliasBuilder.typedef, - Nullability.nonNullable, - invocation.arguments.types); - libraryBuilder.checkBoundsInType( - aliasedType, typeEnvironment, uri, invocation.fileOffset, - allowSuperBounded: false, inferred: inferred); - DartType unaliasedType = aliasedType.unalias; - List? invocationTypeArguments = null; - if (unaliasedType is InterfaceType) { - invocationTypeArguments = unaliasedType.typeArguments; + if (replacement == null) { + delayedTypeAliasedConstructorInvocations.add(invocation); + } else { + invocation.parent?.replaceChild(invocation, replacement); } - Arguments invocationArguments = forest.createArguments( - noLocation, invocation.arguments.positional, - types: invocationTypeArguments, named: invocation.arguments.named); - invocation.parent?.replaceChild( - invocation, - new ConstructorInvocation(invocation.target, invocationArguments, - isConst: invocation.isConst)); } typeAliasedConstructorInvocations.clear(); } @@ -1603,35 +1678,34 @@ class BodyBuilder extends StackListenerImpl typeAliasedFactoryInvocations.toList(); typeAliasedFactoryInvocations.clear(); for (TypeAliasedFactoryInvocation invocation in invocations) { - if (!invocation.hasBeenInferred) { - assert( - isOrphaned(invocation), "Node $invocation has not been inferred."); - continue; + assert(invocation.hasBeenInferred || isOrphaned(invocation), + "Node $invocation has not been inferred."); + + Expression? replacement; + if (invocation.hasBeenInferred) { + bool inferred = !hasExplicitTypeArguments(invocation.arguments); + DartType aliasedType = new TypedefType( + invocation.typeAliasBuilder.typedef, + Nullability.nonNullable, + invocation.arguments.types); + libraryBuilder.checkBoundsInType( + aliasedType, typeEnvironment, uri, invocation.fileOffset, + allowSuperBounded: false, inferred: inferred); + DartType unaliasedType = aliasedType.unalias; + List? invocationTypeArguments = null; + if (unaliasedType is TypeDeclarationType) { + invocationTypeArguments = unaliasedType.typeArguments; + } + Arguments invocationArguments = forest.createArguments( + noLocation, invocation.arguments.positional, + types: invocationTypeArguments, + named: invocation.arguments.named, + hasExplicitTypeArguments: + hasExplicitTypeArguments(invocation.arguments)); + replacement = _resolveRedirectingFactoryTarget(invocation.target, + invocationArguments, invocation.fileOffset, invocation.isConst); } - bool inferred = !hasExplicitTypeArguments(invocation.arguments); - DartType aliasedType = new TypedefType( - invocation.typeAliasBuilder.typedef, - Nullability.nonNullable, - invocation.arguments.types); - libraryBuilder.checkBoundsInType( - aliasedType, typeEnvironment, uri, invocation.fileOffset, - allowSuperBounded: false, inferred: inferred); - DartType unaliasedType = aliasedType.unalias; - List? invocationTypeArguments = null; - if (unaliasedType is TypeDeclarationType) { - invocationTypeArguments = unaliasedType.typeArguments; - } - Arguments invocationArguments = forest.createArguments( - noLocation, invocation.arguments.positional, - types: invocationTypeArguments, - named: invocation.arguments.named, - hasExplicitTypeArguments: - hasExplicitTypeArguments(invocation.arguments)); - Expression? replacement = _resolveRedirectingFactoryTarget( - invocation.target, - invocationArguments, - invocation.fileOffset, - invocation.isConst); + if (replacement == null) { delayedTypeAliasedFactoryInvocations.add(invocation); } else { @@ -1677,12 +1751,27 @@ class BodyBuilder extends StackListenerImpl } } } + if (delayedTypeAliasedConstructorInvocations.isNotEmpty) { + _unaliasTypeAliasedConstructorInvocations( + delayedTypeAliasedConstructorInvocations); + if (delayedTypeAliasedConstructorInvocations.isNotEmpty) { + for (ConstructorInvocation invocation + in delayedTypeAliasedConstructorInvocations) { + internalProblem( + fasta.templateInternalProblemUnhandled.withArguments( + invocation.target.name.text, 'performDelayedActions'), + invocation.fileOffset, + uri); + } + } + } } @override bool get hasDelayedActions { return delayedRedirectingFactoryInvocations.isNotEmpty || - delayedTypeAliasedFactoryInvocations.isNotEmpty; + delayedTypeAliasedFactoryInvocations.isNotEmpty || + delayedTypeAliasedConstructorInvocations.isNotEmpty; } void _finishVariableMetadata() { @@ -5483,6 +5572,7 @@ class BodyBuilder extends StackListenerImpl super.push(constantContext); _insideOfFormalParameterType = false; constantContext = ConstantContext.required; + _defaultValueNestingLevel++; } @override @@ -5491,6 +5581,7 @@ class BodyBuilder extends StackListenerImpl Object? defaultValueExpression = pop(); constantContext = pop() as ConstantContext; push(defaultValueExpression); + _defaultValueNestingLevel--; } @override @@ -5967,14 +6058,17 @@ class BodyBuilder extends StackListenerImpl libraryBuilder.checkBoundsInConstructorInvocation( node, typeEnvironment, uri); } else { - TypeAliasedConstructorInvocation constructorInvocation = + TypeAliasedConstructorInvocation typeAliasedConstructorInvocation = node = new TypeAliasedConstructorInvocation( typeAliasBuilder, target, arguments, isConst: isConst) ..fileOffset = charOffset; // No type arguments were passed, so we need not check bounds. assert(arguments.types.isEmpty); - typeAliasedConstructorInvocations.add(constructorInvocation); + if (_createdStaticInvocationsNeedPostProcessing) { + typeAliasedConstructorInvocations + .add(typeAliasedConstructorInvocation); + } } return node; } else { @@ -5998,25 +6092,29 @@ class BodyBuilder extends StackListenerImpl } StaticInvocation node; if (typeAliasBuilder == null) { - FactoryConstructorInvocation factoryInvocation = + FactoryConstructorInvocation factoryConstructorInvocation = new FactoryConstructorInvocation(target, arguments, isConst: isConst) ..fileOffset = charOffset; libraryBuilder.checkBoundsInFactoryInvocation( - factoryInvocation, typeEnvironment, uri, + factoryConstructorInvocation, typeEnvironment, uri, inferred: !hasExplicitTypeArguments(arguments)); - redirectingFactoryInvocations.add(factoryInvocation); - node = factoryInvocation; + if (_createdStaticInvocationsNeedPostProcessing) { + redirectingFactoryInvocations.add(factoryConstructorInvocation); + } + node = factoryConstructorInvocation; } else { - TypeAliasedFactoryInvocation constructorInvocation = + TypeAliasedFactoryInvocation typeAliasedFactoryInvocation = new TypeAliasedFactoryInvocation( typeAliasBuilder, target, arguments, isConst: isConst) ..fileOffset = charOffset; // No type arguments were passed, so we need not check bounds. assert(arguments.types.isEmpty); - typeAliasedFactoryInvocations.add(constructorInvocation); - node = constructorInvocation; + if (_createdStaticInvocationsNeedPostProcessing) { + typeAliasedFactoryInvocations.add(typeAliasedFactoryInvocation); + } + node = typeAliasedFactoryInvocation; } return node; } else { diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder_context.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder_context.dart index 1fbda272468..8d124cf1902 100644 --- a/pkg/front_end/lib/src/fasta/kernel/body_builder_context.dart +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder_context.dart @@ -49,6 +49,12 @@ abstract class BodyBuilderContext { : _declarationContext = new BodyBuilderDeclarationContext( libraryBuilder, declarationBuilder); + bool get hasImmediateOutlineExpressionsBuilt; + + bool get needsImmediateValuesBuiltAsOutlineExpressions; + + bool get hasFormalParameters; + String get memberName { throw new UnsupportedError('${runtimeType}.memberName'); } @@ -486,6 +492,22 @@ class _TopLevelBodyBuilderDeclarationContext class LibraryBodyBuilderContext extends BodyBuilderContext { LibraryBodyBuilderContext(SourceLibraryBuilder libraryBuilder) : super(libraryBuilder, null, isDeclarationInstanceMember: false); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Libraries don't have immediate values. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Libraries don't have immediate values relevant in outlines, so all of + // them from the empty set can be assumed to have been processed. + return true; + } + + @override + bool get hasFormalParameters => false; } mixin _DeclarationBodyBuilderContext @@ -501,6 +523,22 @@ class ClassBodyBuilderContext extends BodyBuilderContext ClassBodyBuilderContext(SourceClassBuilder sourceClassBuilder) : super(sourceClassBuilder.libraryBuilder, sourceClassBuilder, isDeclarationInstanceMember: false); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Classes don't have immediate values. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Classes don't have immediate values relevant in outlines, so all of + // them from the empty set can be assumed to have been processed. + return true; + } + + @override + bool get hasFormalParameters => false; } class EnumBodyBuilderContext extends BodyBuilderContext @@ -508,6 +546,22 @@ class EnumBodyBuilderContext extends BodyBuilderContext EnumBodyBuilderContext(SourceEnumBuilder sourceEnumBuilder) : super(sourceEnumBuilder.libraryBuilder, sourceEnumBuilder, isDeclarationInstanceMember: false); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Enums don't have immediate values relevant in outlines. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Enums don't have immediate values relevant in outlines, so all of + // them from the empty set can be assumed to have been processed. + return true; + } + + @override + bool get hasFormalParameters => false; } class ExtensionBodyBuilderContext extends BodyBuilderContext @@ -515,6 +569,22 @@ class ExtensionBodyBuilderContext extends BodyBuilderContext ExtensionBodyBuilderContext(SourceExtensionBuilder sourceExtensionBuilder) : super(sourceExtensionBuilder.libraryBuilder, sourceExtensionBuilder, isDeclarationInstanceMember: false); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Extensions don't have immediate values. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Extensions don't have immediate values relevant in outlines, so all of + // them from the empty set can be assumed to have been processed. + return true; + } + + @override + bool get hasFormalParameters => false; } class ExtensionTypeBodyBuilderContext extends BodyBuilderContext @@ -525,12 +595,45 @@ class ExtensionTypeBodyBuilderContext extends BodyBuilderContext : super(sourceExtensionTypeDeclarationBuilder.libraryBuilder, sourceExtensionTypeDeclarationBuilder, isDeclarationInstanceMember: false); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Extension type declarations don't have immediate values. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Extension type declarations don't have immediate values relevant in + // outlines, so all of them from the empty set can be assumed to have been + // processed. + return true; + } + + @override + bool get hasFormalParameters => false; } class TypedefBodyBuilderContext extends BodyBuilderContext { TypedefBodyBuilderContext(SourceTypeAliasBuilder sourceTypeAliasBuilder) : super(sourceTypeAliasBuilder.libraryBuilder, null, isDeclarationInstanceMember: false); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Typedefs don't have immediate values. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Typedefs don't have immediate values relevant in outlines, so all of + // them from the empty set can be assumed to have been processed. + return true; + } + + @override + bool get hasFormalParameters => false; } mixin _MemberBodyBuilderContext @@ -589,6 +692,20 @@ class FieldBodyBuilderContext extends BodyBuilderContext ? ConstantContext.required : ConstantContext.none; } + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Const field initializers are a part of outline. + return _member.isConst; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + return _member.hasOutlineExpressionsBuilt; + } + + @override + bool get hasFormalParameters => false; } mixin _FunctionBodyBuilderContextMixin @@ -687,6 +804,19 @@ class ProcedureBodyBuilderContext extends BodyBuilderContext ProcedureBodyBuilderContext(this._member) : super(_member.libraryBuilder, _member.declarationBuilder, isDeclarationInstanceMember: _member.isDeclarationInstanceMember); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + return _member.needsDefaultValuesBuiltAsOutlineExpressions; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + return _member.hasBuiltOutlineExpressions; + } + + @override + bool get hasFormalParameters => true; } mixin _ConstructorBodyBuilderContextMixin @@ -767,6 +897,22 @@ class ConstructorBodyBuilderContext extends BodyBuilderContext return !_declarationContext.isObjectClass(coreTypes) && !isExternalConstructor; } + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // For modular compilation we need to include default values for optional + // and named parameters generative constructors to support forwarding + // constructors in mixin applications. + return true; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + return _member.hasBuiltOutlineExpressions; + } + + @override + bool get hasFormalParameters => true; } class ExtensionTypeConstructorBodyBuilderContext extends BodyBuilderContext @@ -786,6 +932,22 @@ class ExtensionTypeConstructorBodyBuilderContext extends BodyBuilderContext bool isConstructorCyclic(String name) { return _declarationContext.isConstructorCyclic(_member.name, name); } + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // For modular compilation we need to include default values for optional + // and named parameters generative constructors to support forwarding + // constructors in mixin applications. + return true; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + return _member.hasBuiltOutlineExpressions; + } + + @override + bool get hasFormalParameters => true; } class FactoryBodyBuilderContext extends BodyBuilderContext @@ -808,6 +970,22 @@ class FactoryBodyBuilderContext extends BodyBuilderContext DartType get returnTypeContext { return _member.function.returnType; } + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // For modular compilation we need to include default values for optional + // and named parameters in several cases for const constructors to enable + // constant evaluation, + return _member.parent!.isFactory && _member.parent!.isConst; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + return _member.hasBuiltOutlineExpressions; + } + + @override + bool get hasFormalParameters => true; } class RedirectingFactoryBodyBuilderContext extends BodyBuilderContext @@ -828,6 +1006,22 @@ class RedirectingFactoryBodyBuilderContext extends BodyBuilderContext String get redirectingFactoryTargetName { return _member.redirectionTarget.fullNameForErrors; } + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // For modular compilation we need to include default values for optional + // and named parameters in several cases for const constructors to enable + // constant evaluation, + return _member.parent!.isFactory && _member.parent!.isConst; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + return _member.hasBuiltOutlineExpressions; + } + + @override + bool get hasFormalParameters => true; } class ParameterBodyBuilderContext extends BodyBuilderContext { @@ -846,6 +1040,21 @@ class ParameterBodyBuilderContext extends BodyBuilderContext { : super(libraryBuilder, declarationBuilder, isDeclarationInstanceMember: formalParameterBuilder.isDeclarationInstanceMember); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Parameters are covered by their parents rather than individually. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Parameters are covered by their parents rather than individually. + return true; + } + + @override + bool get hasFormalParameters => false; } class ExpressionCompilerProcedureBodyBuildContext extends BodyBuilderContext @@ -858,4 +1067,20 @@ class ExpressionCompilerProcedureBodyBuildContext extends BodyBuilderContext {required bool isDeclarationInstanceMember}) : super(listener.libraryBuilder, listener.currentDeclaration, isDeclarationInstanceMember: isDeclarationInstanceMember); + + @override + bool get needsImmediateValuesBuiltAsOutlineExpressions { + // Expressions don't have immediate values relevant in outlines. + return false; + } + + @override + bool get hasImmediateOutlineExpressionsBuilt { + // Expressions don't have immediate values relevant in outlines, so all of + // them from the empty set can be assumed to have been processed. + return true; + } + + @override + bool get hasFormalParameters => false; } diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart index 25ccf51baca..65b044a1d2a 100644 --- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart +++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart @@ -686,7 +686,7 @@ class TypeAliasedFactoryInvocation extends StaticInvocation @override String toString() { - return "TypeAliasedConstructorInvocation(${toStringInternal()})"; + return "TypeAliasedFactoryInvocation(${toStringInternal()})"; } @override diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart index afb40a20a12..cd5a61cbe2c 100644 --- a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart @@ -484,6 +484,8 @@ class SourceFieldBuilder extends SourceMemberBuilderImpl _constInitializerToken = null; } + bool get hasOutlineExpressionsBuilt => _constInitializerToken == null; + DartType get fieldType => _fieldEncoding.type; void set fieldType(DartType value) { diff --git a/pkg/front_end/lib/src/fasta/source/source_function_builder.dart b/pkg/front_end/lib/src/fasta/source/source_function_builder.dart index 372f9ceb9c8..62f2e2b88b6 100644 --- a/pkg/front_end/lib/src/fasta/source/source_function_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_function_builder.dart @@ -468,14 +468,25 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl function.returnType = type; } - bool _hasBuiltOutlineExpressions = false; + bool hasBuiltOutlineExpressions = false; + + bool get needsDefaultValuesBuiltAsOutlineExpressions { + if (formals != null) { + for (FormalParameterBuilder formal in formals!) { + if (formal.needsDefaultValuesBuiltAsOutlineExpressions) { + return true; + } + } + } + return false; + } @override void buildOutlineExpressions( ClassHierarchy classHierarchy, List delayedActionPerformers, List delayedDefaultValueCloners) { - if (!_hasBuiltOutlineExpressions) { + if (!hasBuiltOutlineExpressions) { DeclarationBuilder? classOrExtensionBuilder = isClassMember || isExtensionMember || isExtensionTypeMember ? parent as DeclarationBuilder @@ -508,7 +519,7 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl libraryBuilder, delayedActionPerformers); } } - _hasBuiltOutlineExpressions = true; + hasBuiltOutlineExpressions = true; } } diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt index 6277fd7f0ac..9c4a8b761a9 100644 --- a/pkg/front_end/test/spell_checking_list_common.txt +++ b/pkg/front_end/test/spell_checking_list_common.txt @@ -459,6 +459,7 @@ circularities circularity circumstance circumstances +clarifying clashing class classes @@ -564,6 +565,7 @@ completer completion complex compliance +complication component components composed @@ -2037,6 +2039,7 @@ neighbors neither nest nested +nestedness nesting net never @@ -2541,6 +2544,7 @@ refinements reflecting reflects regardless +regards region regions register diff --git a/pkg/front_end/testcases/general/issue55152.dart b/pkg/front_end/testcases/general/issue55152.dart new file mode 100644 index 00000000000..720a25ac748 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +class A { + const A(); + const factory A.redir() = A; +} + +typedef TA = A; + +enum E { + // Should be resolved to `const A()`. + element(TA.redir()); + + final A a; + + const E(this.a); +} diff --git a/pkg/front_end/testcases/general/issue55152.dart.strong.expect b/pkg/front_end/testcases/general/issue55152.dart.strong.expect new file mode 100644 index 00000000000..bab115476ea --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.strong.expect @@ -0,0 +1,38 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::•*/ + return new self::A::•(); +} +class E extends core::_Enum /*isEnum*/ { + static const field core::List values = #C5; + final field self::A a; + enum-element static const field self::E element = #C4; + const constructor •(core::int #index, core::String #name, self::A a) → self::E + : self::E::a = a, super core::_Enum::•(#index, #name) + ; + method _enumToString() → core::String + return "E.${this.{core::_Enum::_name}{core::String}}"; +} + +constants { + #C1 = self::A {} + #C2 = 0 + #C3 = "element" + #C4 = self::E {a:#C1, index:#C2, _name:#C3} + #C5 = [#C4] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152.dart: +- A. (from org-dartlang-testcase:///issue55152.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- E. (from org-dartlang-testcase:///issue55152.dart:18:9) +- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart) diff --git a/pkg/front_end/testcases/general/issue55152.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue55152.dart.strong.transformed.expect new file mode 100644 index 00000000000..bab115476ea --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.strong.transformed.expect @@ -0,0 +1,38 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::•*/ + return new self::A::•(); +} +class E extends core::_Enum /*isEnum*/ { + static const field core::List values = #C5; + final field self::A a; + enum-element static const field self::E element = #C4; + const constructor •(core::int #index, core::String #name, self::A a) → self::E + : self::E::a = a, super core::_Enum::•(#index, #name) + ; + method _enumToString() → core::String + return "E.${this.{core::_Enum::_name}{core::String}}"; +} + +constants { + #C1 = self::A {} + #C2 = 0 + #C3 = "element" + #C4 = self::E {a:#C1, index:#C2, _name:#C3} + #C5 = [#C4] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152.dart: +- A. (from org-dartlang-testcase:///issue55152.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- E. (from org-dartlang-testcase:///issue55152.dart:18:9) +- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart) diff --git a/pkg/front_end/testcases/general/issue55152.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue55152.dart.textual_outline.expect new file mode 100644 index 00000000000..3717755cef2 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.textual_outline.expect @@ -0,0 +1,13 @@ +class A { + const A(); + const factory A.redir() = A; +} + +typedef TA = A; + +enum E { + element(TA.redir()); + + final A a; + const E(this.a); +} diff --git a/pkg/front_end/testcases/general/issue55152.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue55152.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..196a6e4ff47 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.textual_outline_modelled.expect @@ -0,0 +1,13 @@ +class A { + const A(); + const factory A.redir() = A; +} + +enum E { + element(TA.redir()); + + final A a; + const E(this.a); +} + +typedef TA = A; diff --git a/pkg/front_end/testcases/general/issue55152.dart.weak.expect b/pkg/front_end/testcases/general/issue55152.dart.weak.expect new file mode 100644 index 00000000000..cf9f66a287f --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.weak.expect @@ -0,0 +1,38 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::•*/ + return new self::A::•(); +} +class E extends core::_Enum /*isEnum*/ { + static const field core::List values = #C5; + final field self::A a; + enum-element static const field self::E element = #C4; + const constructor •(core::int #index, core::String #name, self::A a) → self::E + : self::E::a = a, super core::_Enum::•(#index, #name) + ; + method _enumToString() → core::String + return "E.${this.{core::_Enum::_name}{core::String}}"; +} + +constants { + #C1 = self::A {} + #C2 = 0 + #C3 = "element" + #C4 = self::E {a:#C1, index:#C2, _name:#C3} + #C5 = [#C4] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152.dart: +- A. (from org-dartlang-testcase:///issue55152.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- E. (from org-dartlang-testcase:///issue55152.dart:18:9) +- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart) diff --git a/pkg/front_end/testcases/general/issue55152.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue55152.dart.weak.modular.expect new file mode 100644 index 00000000000..cf9f66a287f --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.weak.modular.expect @@ -0,0 +1,38 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::•*/ + return new self::A::•(); +} +class E extends core::_Enum /*isEnum*/ { + static const field core::List values = #C5; + final field self::A a; + enum-element static const field self::E element = #C4; + const constructor •(core::int #index, core::String #name, self::A a) → self::E + : self::E::a = a, super core::_Enum::•(#index, #name) + ; + method _enumToString() → core::String + return "E.${this.{core::_Enum::_name}{core::String}}"; +} + +constants { + #C1 = self::A {} + #C2 = 0 + #C3 = "element" + #C4 = self::E {a:#C1, index:#C2, _name:#C3} + #C5 = [#C4] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152.dart: +- A. (from org-dartlang-testcase:///issue55152.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- E. (from org-dartlang-testcase:///issue55152.dart:18:9) +- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart) diff --git a/pkg/front_end/testcases/general/issue55152.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue55152.dart.weak.outline.expect new file mode 100644 index 00000000000..95cf0704757 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.weak.outline.expect @@ -0,0 +1,28 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::•*/ + return new self::A::•(); +} +class E extends core::_Enum /*isEnum*/ { + static const field core::List values = const [self::E::element]; + final field self::A a; + enum-element static const field self::E element = const self::E::•(0, "element", const self::A::•()); + const constructor •(core::int #index, core::String #name, self::A a) → self::E + : self::E::a = a, super core::_Enum::•(#index, #name) + ; + method _enumToString() → core::String + return "E.${this.{core::_Enum::_name}{core::String}}"; +} + + +Extra constant evaluation status: +Evaluated: ListLiteral @ org-dartlang-testcase:///issue55152.dart:12:6 -> ListConstant(const [const E{E.a: const A{}, _Enum.index: 0, _Enum._name: "element"}]) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152.dart:14:3 -> InstanceConstant(const E{E.a: const A{}, _Enum.index: 0, _Enum._name: "element"}) +Extra constant evaluation: evaluated: 9, effectively constant: 2 diff --git a/pkg/front_end/testcases/general/issue55152.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue55152.dart.weak.transformed.expect new file mode 100644 index 00000000000..cf9f66a287f --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152.dart.weak.transformed.expect @@ -0,0 +1,38 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::•*/ + return new self::A::•(); +} +class E extends core::_Enum /*isEnum*/ { + static const field core::List values = #C5; + final field self::A a; + enum-element static const field self::E element = #C4; + const constructor •(core::int #index, core::String #name, self::A a) → self::E + : self::E::a = a, super core::_Enum::•(#index, #name) + ; + method _enumToString() → core::String + return "E.${this.{core::_Enum::_name}{core::String}}"; +} + +constants { + #C1 = self::A {} + #C2 = 0 + #C3 = "element" + #C4 = self::E {a:#C1, index:#C2, _name:#C3} + #C5 = [#C4] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152.dart: +- A. (from org-dartlang-testcase:///issue55152.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- E. (from org-dartlang-testcase:///issue55152.dart:18:9) +- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart) diff --git a/pkg/front_end/testcases/general/issue55152_2.dart b/pkg/front_end/testcases/general/issue55152_2.dart new file mode 100644 index 00000000000..a680a616f4e --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart @@ -0,0 +1,75 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +class A { + const A(); + const factory A.redir() = B; + const factory A.redir2() = B; + const A.named(); + const A.named2(); + const factory A.selfRedir() = A.named; + const factory A.selfRedir2() = A.named2; +} + +class B extends A { + const B(); +} + +typedef TA = A; + +test(@TA.redir() int x, @TA.named() int x2, @A.redir() int x3, + @A.selfRedir() int x4) { + @TA.redir2() + int localVariable = 0; + + @TA.redir2() + void localFunction() {} + + @TA.named2() + int localVariable2 = 0; + + @TA.named2() + void localFunction2() {} + + @A.redir2() + int localVariable3 = 0; + + @A.redir2() + void localFunction3() {} + + @A.selfRedir2() + int localVariable4 = 0; + + @A.selfRedir2() + void localFunction4() {} +} + +class Test { + test(@TA.redir() int x, @TA.named() int x2, @A.redir() int x3, + @A.selfRedir() int x4) { + @TA.redir2() + int localVariable = 0; + + @TA.redir2() + void localFunction() {} + + @TA.named2() + int localVariable2 = 0; + + @TA.named2() + void localFunction2() {} + + @A.redir2() + int localVariable3 = 0; + + @A.redir2() + void localFunction3() {} + + @A.selfRedir2() + int localVariable4 = 0; + + @A.selfRedir2() + void localFunction4() {} + } +} diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.strong.expect b/pkg/front_end/testcases/general/issue55152_2.dart.strong.expect new file mode 100644 index 00000000000..e9b6ee50a64 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.strong.expect @@ -0,0 +1,76 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + const constructor named2() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory redir2() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); + static factory selfRedir2() → self::A /* redirection-target: self::A::named2 */ + return new self::A::named2(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object { + synthetic constructor •() → self::Test + : super core::Object::•() + ; + method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} + } +} +static method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} +} + +constants { + #C1 = self::B {} + #C2 = self::A {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_2.dart: +- B. (from org-dartlang-testcase:///issue55152_2.dart:16:9) +- A. (from org-dartlang-testcase:///issue55152_2.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- A.named (from org-dartlang-testcase:///issue55152_2.dart:9:9) +- A.named2 (from org-dartlang-testcase:///issue55152_2.dart:10:9) diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue55152_2.dart.strong.transformed.expect new file mode 100644 index 00000000000..e9b6ee50a64 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.strong.transformed.expect @@ -0,0 +1,76 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + const constructor named2() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory redir2() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); + static factory selfRedir2() → self::A /* redirection-target: self::A::named2 */ + return new self::A::named2(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object { + synthetic constructor •() → self::Test + : super core::Object::•() + ; + method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} + } +} +static method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} +} + +constants { + #C1 = self::B {} + #C2 = self::A {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_2.dart: +- B. (from org-dartlang-testcase:///issue55152_2.dart:16:9) +- A. (from org-dartlang-testcase:///issue55152_2.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- A.named (from org-dartlang-testcase:///issue55152_2.dart:9:9) +- A.named2 (from org-dartlang-testcase:///issue55152_2.dart:10:9) diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue55152_2.dart.textual_outline.expect new file mode 100644 index 00000000000..3f01a68602d --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.textual_outline.expect @@ -0,0 +1,23 @@ +class A { + const A(); + const factory A.redir() = B; + const factory A.redir2() = B; + const A.named(); + const A.named2(); + const factory A.selfRedir() = A.named; + const factory A.selfRedir2() = A.named2; +} + +class B extends A { + const B(); +} + +typedef TA = A; + +test(@TA.redir() int x, @TA.named() int x2, @A.redir() int x3, + @A.selfRedir() int x4) {} + +class Test { + test(@TA.redir() int x, @TA.named() int x2, @A.redir() int x3, + @A.selfRedir() int x4) {} +} diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue55152_2.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..66ad8eeee01 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.textual_outline_modelled.expect @@ -0,0 +1,23 @@ +class A { + const A(); + const A.named(); + const A.named2(); + const factory A.redir() = B; + const factory A.redir2() = B; + const factory A.selfRedir() = A.named; + const factory A.selfRedir2() = A.named2; +} + +class B extends A { + const B(); +} + +class Test { + test(@TA.redir() int x, @TA.named() int x2, @A.redir() int x3, + @A.selfRedir() int x4) {} +} + +test(@TA.redir() int x, @TA.named() int x2, @A.redir() int x3, + @A.selfRedir() int x4) {} + +typedef TA = A; diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.weak.expect b/pkg/front_end/testcases/general/issue55152_2.dart.weak.expect new file mode 100644 index 00000000000..e9b6ee50a64 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.weak.expect @@ -0,0 +1,76 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + const constructor named2() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory redir2() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); + static factory selfRedir2() → self::A /* redirection-target: self::A::named2 */ + return new self::A::named2(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object { + synthetic constructor •() → self::Test + : super core::Object::•() + ; + method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} + } +} +static method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} +} + +constants { + #C1 = self::B {} + #C2 = self::A {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_2.dart: +- B. (from org-dartlang-testcase:///issue55152_2.dart:16:9) +- A. (from org-dartlang-testcase:///issue55152_2.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- A.named (from org-dartlang-testcase:///issue55152_2.dart:9:9) +- A.named2 (from org-dartlang-testcase:///issue55152_2.dart:10:9) diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue55152_2.dart.weak.modular.expect new file mode 100644 index 00000000000..e9b6ee50a64 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.weak.modular.expect @@ -0,0 +1,76 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + const constructor named2() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory redir2() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); + static factory selfRedir2() → self::A /* redirection-target: self::A::named2 */ + return new self::A::named2(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object { + synthetic constructor •() → self::Test + : super core::Object::•() + ; + method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} + } +} +static method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} +} + +constants { + #C1 = self::B {} + #C2 = self::A {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_2.dart: +- B. (from org-dartlang-testcase:///issue55152_2.dart:16:9) +- A. (from org-dartlang-testcase:///issue55152_2.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- A.named (from org-dartlang-testcase:///issue55152_2.dart:9:9) +- A.named2 (from org-dartlang-testcase:///issue55152_2.dart:10:9) diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue55152_2.dart.weak.outline.expect new file mode 100644 index 00000000000..1fd23349c72 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.weak.outline.expect @@ -0,0 +1,37 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + const constructor named2() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory redir2() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); + static factory selfRedir2() → self::A /* redirection-target: self::A::named2 */ + return new self::A::named2(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object { + synthetic constructor •() → self::Test + ; + method test(core::int x, core::int x2, core::int x3, core::int x4) → dynamic + ; +} +static method test(core::int x, core::int x2, core::int x3, core::int x4) → dynamic + ; diff --git a/pkg/front_end/testcases/general/issue55152_2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue55152_2.dart.weak.transformed.expect new file mode 100644 index 00000000000..e9b6ee50a64 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_2.dart.weak.transformed.expect @@ -0,0 +1,76 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + const constructor named2() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory redir2() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); + static factory selfRedir2() → self::A /* redirection-target: self::A::named2 */ + return new self::A::named2(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object { + synthetic constructor •() → self::Test + : super core::Object::•() + ; + method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} + } +} +static method test(@#C1 core::int x, @#C2 core::int x2, @#C1 core::int x3, @#C2 core::int x4) → dynamic { + @#C1 core::int localVariable = 0; + @#C1 + function localFunction() → void {} + @#C2 core::int localVariable2 = 0; + @#C2 + function localFunction2() → void {} + @#C1 core::int localVariable3 = 0; + @#C1 + function localFunction3() → void {} + @#C2 core::int localVariable4 = 0; + @#C2 + function localFunction4() → void {} +} + +constants { + #C1 = self::B {} + #C2 = self::A {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_2.dart: +- B. (from org-dartlang-testcase:///issue55152_2.dart:16:9) +- A. (from org-dartlang-testcase:///issue55152_2.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- A.named (from org-dartlang-testcase:///issue55152_2.dart:9:9) +- A.named2 (from org-dartlang-testcase:///issue55152_2.dart:10:9) diff --git a/pkg/front_end/testcases/general/issue55152_3.dart b/pkg/front_end/testcases/general/issue55152_3.dart new file mode 100644 index 00000000000..d283689ae2c --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart @@ -0,0 +1,25 @@ +// Copyright (c) 2024, 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. + +// `const Alias2.impl()` is at nestedness level 2 of default values, and we +// need to make sure we don't crash in that case. Compiling the program still +// results in a compile-time error, due to function expressions not being const +// values, but it shouldn't crash. +class Class { + const Class.named( + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + const [Alias.impl()])}); +} + +typedef Alias = Const; + +typedef Alias2 = Const; + +abstract class Const { + const factory Const.impl() = _ConstImpl; +} + +class _ConstImpl implements Const { + const _ConstImpl(); +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.strong.expect b/pkg/front_end/testcases/general/issue55152_3.dart.strong.expect new file mode 100644 index 00000000000..7e0aa564119 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.strong.expect @@ -0,0 +1,29 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. +// {dynamic x = (({dynamic y = const [Alias2.impl()]}) => +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +typedef Alias = self::Const; +typedef Alias2 = self::Const; +class Class extends core::Object /*hasConstConstructor*/ { + const constructor named({dynamic x = invalid-expression "pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"}) → self::Class + : super core::Object::•() + ; +} +abstract class Const extends core::Object { + static factory impl() → self::Const /* redirection-target: self::_ConstImpl::•*/ + return new self::_ConstImpl::•(); +} +class _ConstImpl extends core::Object implements self::Const /*hasConstConstructor*/ { + const constructor •() → self::_ConstImpl + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue55152_3.dart.strong.transformed.expect new file mode 100644 index 00000000000..7e0aa564119 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.strong.transformed.expect @@ -0,0 +1,29 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. +// {dynamic x = (({dynamic y = const [Alias2.impl()]}) => +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +typedef Alias = self::Const; +typedef Alias2 = self::Const; +class Class extends core::Object /*hasConstConstructor*/ { + const constructor named({dynamic x = invalid-expression "pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"}) → self::Class + : super core::Object::•() + ; +} +abstract class Const extends core::Object { + static factory impl() → self::Const /* redirection-target: self::_ConstImpl::•*/ + return new self::_ConstImpl::•(); +} +class _ConstImpl extends core::Object implements self::Const /*hasConstConstructor*/ { + const constructor •() → self::_ConstImpl + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue55152_3.dart.textual_outline.expect new file mode 100644 index 00000000000..dd26a8a3168 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.textual_outline.expect @@ -0,0 +1,17 @@ +class Class { + const Class.named( + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + const [Alias.impl()])}); +} + +typedef Alias = Const; + +typedef Alias2 = Const; + +abstract class Const { + const factory Const.impl() = _ConstImpl; +} + +class _ConstImpl implements Const { + const _ConstImpl(); +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue55152_3.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..ae8738786f2 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.textual_outline_modelled.expect @@ -0,0 +1,17 @@ +abstract class Const { + const factory Const.impl() = _ConstImpl; +} + +class Class { + const Class.named( + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + const [Alias.impl()])}); +} + +class _ConstImpl implements Const { + const _ConstImpl(); +} + +typedef Alias = Const; + +typedef Alias2 = Const; diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.weak.expect b/pkg/front_end/testcases/general/issue55152_3.dart.weak.expect new file mode 100644 index 00000000000..7e0aa564119 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.weak.expect @@ -0,0 +1,29 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. +// {dynamic x = (({dynamic y = const [Alias2.impl()]}) => +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +typedef Alias = self::Const; +typedef Alias2 = self::Const; +class Class extends core::Object /*hasConstConstructor*/ { + const constructor named({dynamic x = invalid-expression "pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"}) → self::Class + : super core::Object::•() + ; +} +abstract class Const extends core::Object { + static factory impl() → self::Const /* redirection-target: self::_ConstImpl::•*/ + return new self::_ConstImpl::•(); +} +class _ConstImpl extends core::Object implements self::Const /*hasConstConstructor*/ { + const constructor •() → self::_ConstImpl + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue55152_3.dart.weak.modular.expect new file mode 100644 index 00000000000..7e0aa564119 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.weak.modular.expect @@ -0,0 +1,29 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. +// {dynamic x = (({dynamic y = const [Alias2.impl()]}) => +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +typedef Alias = self::Const; +typedef Alias2 = self::Const; +class Class extends core::Object /*hasConstConstructor*/ { + const constructor named({dynamic x = invalid-expression "pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"}) → self::Class + : super core::Object::•() + ; +} +abstract class Const extends core::Object { + static factory impl() → self::Const /* redirection-target: self::_ConstImpl::•*/ + return new self::_ConstImpl::•(); +} +class _ConstImpl extends core::Object implements self::Const /*hasConstConstructor*/ { + const constructor •() → self::_ConstImpl + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue55152_3.dart.weak.outline.expect new file mode 100644 index 00000000000..7e0aa564119 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.weak.outline.expect @@ -0,0 +1,29 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. +// {dynamic x = (({dynamic y = const [Alias2.impl()]}) => +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +typedef Alias = self::Const; +typedef Alias2 = self::Const; +class Class extends core::Object /*hasConstConstructor*/ { + const constructor named({dynamic x = invalid-expression "pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"}) → self::Class + : super core::Object::•() + ; +} +abstract class Const extends core::Object { + static factory impl() → self::Const /* redirection-target: self::_ConstImpl::•*/ + return new self::_ConstImpl::•(); +} +class _ConstImpl extends core::Object implements self::Const /*hasConstConstructor*/ { + const constructor •() → self::_ConstImpl + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/general/issue55152_3.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue55152_3.dart.weak.transformed.expect new file mode 100644 index 00000000000..7e0aa564119 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_3.dart.weak.transformed.expect @@ -0,0 +1,29 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. +// {dynamic x = (({dynamic y = const [Alias2.impl()]}) => +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +typedef Alias = self::Const; +typedef Alias2 = self::Const; +class Class extends core::Object /*hasConstConstructor*/ { + const constructor named({dynamic x = invalid-expression "pkg/front_end/testcases/general/issue55152_3.dart:11:21: Error: Not a constant expression. + {dynamic x = (({dynamic y = const [Alias2.impl()]}) => + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"}) → self::Class + : super core::Object::•() + ; +} +abstract class Const extends core::Object { + static factory impl() → self::Const /* redirection-target: self::_ConstImpl::•*/ + return new self::_ConstImpl::•(); +} +class _ConstImpl extends core::Object implements self::Const /*hasConstConstructor*/ { + const constructor •() → self::_ConstImpl + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/general/issue55152_4.dart b/pkg/front_end/testcases/general/issue55152_4.dart new file mode 100644 index 00000000000..803fc1c0b77 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart @@ -0,0 +1,14 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +class A { + const A(); + const factory A.redir() = A; +} + +typedef TA = A; + +const List test1 = const [TA.redir()]; +const List test2 = const [A.redir()]; +const List test3 = const [TA()]; diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.strong.expect b/pkg/front_end/testcases/general/issue55152_4.dart.strong.expect new file mode 100644 index 00000000000..8e419060fee --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.strong.expect @@ -0,0 +1,26 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::• */ + return new self::A::•(); +} +static const field core::List test1 = #C2; +static const field core::List test2 = #C2; +static const field core::List test3 = #C2; + +constants { + #C1 = self::A {} + #C2 = [#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_4.dart: +- A. (from org-dartlang-testcase:///issue55152_4.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue55152_4.dart.strong.transformed.expect new file mode 100644 index 00000000000..8e419060fee --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.strong.transformed.expect @@ -0,0 +1,26 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::• */ + return new self::A::•(); +} +static const field core::List test1 = #C2; +static const field core::List test2 = #C2; +static const field core::List test3 = #C2; + +constants { + #C1 = self::A {} + #C2 = [#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_4.dart: +- A. (from org-dartlang-testcase:///issue55152_4.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue55152_4.dart.textual_outline.expect new file mode 100644 index 00000000000..b4231c32a26 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.textual_outline.expect @@ -0,0 +1,12 @@ +class A { + const A(); + const factory A.redir() = A; +} + +typedef TA = A; + +const List test1 = const [TA.redir()]; + +const List test2 = const [A.redir()]; + +const List test3 = const [TA()]; diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue55152_4.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..f1475d0d2c6 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.textual_outline_modelled.expect @@ -0,0 +1,12 @@ +class A { + const A(); + const factory A.redir() = A; +} + +const List test1 = const [TA.redir()]; + +const List test2 = const [A.redir()]; + +const List test3 = const [TA()]; + +typedef TA = A; diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.weak.expect b/pkg/front_end/testcases/general/issue55152_4.dart.weak.expect new file mode 100644 index 00000000000..3f28ca088e5 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.weak.expect @@ -0,0 +1,26 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::• */ + return new self::A::•(); +} +static const field core::List test1 = #C2; +static const field core::List test2 = #C2; +static const field core::List test3 = #C2; + +constants { + #C1 = self::A {} + #C2 = [#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_4.dart: +- A. (from org-dartlang-testcase:///issue55152_4.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue55152_4.dart.weak.modular.expect new file mode 100644 index 00000000000..3f28ca088e5 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.weak.modular.expect @@ -0,0 +1,26 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::• */ + return new self::A::•(); +} +static const field core::List test1 = #C2; +static const field core::List test2 = #C2; +static const field core::List test3 = #C2; + +constants { + #C1 = self::A {} + #C2 = [#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_4.dart: +- A. (from org-dartlang-testcase:///issue55152_4.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue55152_4.dart.weak.outline.expect new file mode 100644 index 00000000000..b9fef6b140d --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.weak.outline.expect @@ -0,0 +1,22 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::• */ + return new self::A::•(); +} +static const field core::List test1 = const [const self::A::•()]; +static const field core::List test2 = const [const self::A::•()]; +static const field core::List test3 = const [const self::A::•()]; + + +Extra constant evaluation status: +Evaluated: ListLiteral @ org-dartlang-testcase:///issue55152_4.dart:12:23 -> ListConstant(const [const A{}]) +Evaluated: ListLiteral @ org-dartlang-testcase:///issue55152_4.dart:13:23 -> ListConstant(const [const A{}]) +Evaluated: ListLiteral @ org-dartlang-testcase:///issue55152_4.dart:14:23 -> ListConstant(const [const A{}]) +Extra constant evaluation: evaluated: 4, effectively constant: 3 diff --git a/pkg/front_end/testcases/general/issue55152_4.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue55152_4.dart.weak.transformed.expect new file mode 100644 index 00000000000..3f28ca088e5 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_4.dart.weak.transformed.expect @@ -0,0 +1,26 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::A::• */ + return new self::A::•(); +} +static const field core::List test1 = #C2; +static const field core::List test2 = #C2; +static const field core::List test3 = #C2; + +constants { + #C1 = self::A {} + #C2 = [#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_4.dart: +- A. (from org-dartlang-testcase:///issue55152_4.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) diff --git a/pkg/front_end/testcases/general/issue55152_5.dart b/pkg/front_end/testcases/general/issue55152_5.dart new file mode 100644 index 00000000000..bf1efbec2ba --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +class A { + const A(); + const factory A.redir() = B; + const A.named(); + const factory A.selfRedir() = A.named; +} + +class B extends A { + const B(); +} + +typedef TA = A; + +class Test { + final A a; + + const Test.named1() : a = const A(); + const Test.named2() : a = const A.redir(); + const Test.named3() : a = const A.named(); + const Test.named4() : a = const A.selfRedir(); + const Test.named5() : a = const TA(); + const Test.named6() : a = const TA.redir(); + const Test.named7() : a = const TA.named(); + const Test.named8() : a = const TA.selfRedir(); +} diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.strong.expect b/pkg/front_end/testcases/general/issue55152_5.dart.strong.expect new file mode 100644 index 00000000000..1e7823b9411 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.strong.expect @@ -0,0 +1,62 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object /*hasConstConstructor*/ { + final field self::A a; + const constructor named1() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named2() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named3() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named4() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named5() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named6() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named7() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named8() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; +} + +constants { + #C1 = self::A {} + #C2 = self::B {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_5.dart: +- A. (from org-dartlang-testcase:///issue55152_5.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- B. (from org-dartlang-testcase:///issue55152_5.dart:13:9) +- A.named (from org-dartlang-testcase:///issue55152_5.dart:8:9) diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue55152_5.dart.strong.transformed.expect new file mode 100644 index 00000000000..1e7823b9411 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.strong.transformed.expect @@ -0,0 +1,62 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object /*hasConstConstructor*/ { + final field self::A a; + const constructor named1() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named2() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named3() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named4() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named5() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named6() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named7() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named8() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; +} + +constants { + #C1 = self::A {} + #C2 = self::B {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_5.dart: +- A. (from org-dartlang-testcase:///issue55152_5.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- B. (from org-dartlang-testcase:///issue55152_5.dart:13:9) +- A.named (from org-dartlang-testcase:///issue55152_5.dart:8:9) diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue55152_5.dart.textual_outline.expect new file mode 100644 index 00000000000..d2b3e25e035 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.textual_outline.expect @@ -0,0 +1,24 @@ +class A { + const A(); + const factory A.redir() = B; + const A.named(); + const factory A.selfRedir() = A.named; +} + +class B extends A { + const B(); +} + +typedef TA = A; + +class Test { + final A a; + const Test.named1() : a = const A(); + const Test.named2() : a = const A.redir(); + const Test.named3() : a = const A.named(); + const Test.named4() : a = const A.selfRedir(); + const Test.named5() : a = const TA(); + const Test.named6() : a = const TA.redir(); + const Test.named7() : a = const TA.named(); + const Test.named8() : a = const TA.selfRedir(); +} diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue55152_5.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..97defc63d19 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.textual_outline_modelled.expect @@ -0,0 +1,24 @@ +class A { + const A(); + const A.named(); + const factory A.redir() = B; + const factory A.selfRedir() = A.named; +} + +class B extends A { + const B(); +} + +class Test { + const Test.named1() : a = const A(); + const Test.named2() : a = const A.redir(); + const Test.named3() : a = const A.named(); + const Test.named4() : a = const A.selfRedir(); + const Test.named5() : a = const TA(); + const Test.named6() : a = const TA.redir(); + const Test.named7() : a = const TA.named(); + const Test.named8() : a = const TA.selfRedir(); + final A a; +} + +typedef TA = A; diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.weak.expect b/pkg/front_end/testcases/general/issue55152_5.dart.weak.expect new file mode 100644 index 00000000000..1e7823b9411 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.weak.expect @@ -0,0 +1,62 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object /*hasConstConstructor*/ { + final field self::A a; + const constructor named1() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named2() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named3() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named4() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named5() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named6() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named7() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named8() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; +} + +constants { + #C1 = self::A {} + #C2 = self::B {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_5.dart: +- A. (from org-dartlang-testcase:///issue55152_5.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- B. (from org-dartlang-testcase:///issue55152_5.dart:13:9) +- A.named (from org-dartlang-testcase:///issue55152_5.dart:8:9) diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue55152_5.dart.weak.modular.expect new file mode 100644 index 00000000000..1e7823b9411 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.weak.modular.expect @@ -0,0 +1,62 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object /*hasConstConstructor*/ { + final field self::A a; + const constructor named1() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named2() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named3() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named4() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named5() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named6() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named7() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named8() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; +} + +constants { + #C1 = self::A {} + #C2 = self::B {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_5.dart: +- A. (from org-dartlang-testcase:///issue55152_5.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- B. (from org-dartlang-testcase:///issue55152_5.dart:13:9) +- A.named (from org-dartlang-testcase:///issue55152_5.dart:8:9) diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue55152_5.dart.weak.outline.expect new file mode 100644 index 00000000000..57cb5dd1542 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.weak.outline.expect @@ -0,0 +1,61 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object /*hasConstConstructor*/ { + final field self::A a; + const constructor named1() → self::Test + : self::Test::a = const self::A::•(), super core::Object::•() + ; + const constructor named2() → self::Test + : self::Test::a = const self::B::•(), super core::Object::•() + ; + const constructor named3() → self::Test + : self::Test::a = const self::A::named(), super core::Object::•() + ; + const constructor named4() → self::Test + : self::Test::a = const self::A::named(), super core::Object::•() + ; + const constructor named5() → self::Test + : self::Test::a = const self::A::•(), super core::Object::•() + ; + const constructor named6() → self::Test + : self::Test::a = const self::B::•(), super core::Object::•() + ; + const constructor named7() → self::Test + : self::Test::a = const self::A::named(), super core::Object::•() + ; + const constructor named8() → self::Test + : self::Test::a = const self::A::named(), super core::Object::•() + ; +} + + +Extra constant evaluation status: +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:21:35 -> InstanceConstant(const A{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:22:35 -> InstanceConstant(const B{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:23:35 -> InstanceConstant(const A{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:24:35 -> InstanceConstant(const A{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:25:35 -> InstanceConstant(const A{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:26:35 -> InstanceConstant(const B{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:27:35 -> InstanceConstant(const A{}) +Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue55152_5.dart:28:35 -> InstanceConstant(const A{}) +Extra constant evaluation: evaluated: 10, effectively constant: 8 diff --git a/pkg/front_end/testcases/general/issue55152_5.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue55152_5.dart.weak.transformed.expect new file mode 100644 index 00000000000..1e7823b9411 --- /dev/null +++ b/pkg/front_end/testcases/general/issue55152_5.dart.weak.transformed.expect @@ -0,0 +1,62 @@ +library; +import self as self; +import "dart:core" as core; + +typedef TA = self::A; +class A extends core::Object /*hasConstConstructor*/ { + const constructor •() → self::A + : super core::Object::•() + ; + const constructor named() → self::A + : super core::Object::•() + ; + static factory redir() → self::A /* redirection-target: self::B::• */ + return new self::B::•(); + static factory selfRedir() → self::A /* redirection-target: self::A::named */ + return new self::A::named(); +} +class B extends self::A /*hasConstConstructor*/ { + const constructor •() → self::B + : super self::A::•() + ; +} +class Test extends core::Object /*hasConstConstructor*/ { + final field self::A a; + const constructor named1() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named2() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named3() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named4() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named5() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named6() → self::Test + : self::Test::a = #C2, super core::Object::•() + ; + const constructor named7() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; + const constructor named8() → self::Test + : self::Test::a = #C1, super core::Object::•() + ; +} + +constants { + #C1 = self::A {} + #C2 = self::B {} +} + + +Constructor coverage from constants: +org-dartlang-testcase:///issue55152_5.dart: +- A. (from org-dartlang-testcase:///issue55152_5.dart:6:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart) +- B. (from org-dartlang-testcase:///issue55152_5.dart:13:9) +- A.named (from org-dartlang-testcase:///issue55152_5.dart:8:9)