[cfe] Support generic inline class constructors

Change-Id: Ibd12b14e1e8a1811734b4773c842e72a7fcb300c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277684
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Johnni Winther 2022-12-29 23:17:39 +00:00 committed by Commit Queue
parent 2083db9cdb
commit 8e07d492dd
24 changed files with 454 additions and 159 deletions

View file

@ -7,6 +7,7 @@ library fasta.formal_parameter_builder;
import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart' import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'
show FormalParameterKind, FormalParameterKindExtension; show FormalParameterKind, FormalParameterKindExtension;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token; import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
import 'package:front_end/src/fasta/source/constructor_declaration.dart';
import 'package:kernel/ast.dart' import 'package:kernel/ast.dart'
show DartType, DynamicType, Expression, NullLiteral, VariableDeclaration; show DartType, DynamicType, Expression, NullLiteral, VariableDeclaration;
import 'package:kernel/class_hierarchy.dart'; import 'package:kernel/class_hierarchy.dart';
@ -221,10 +222,14 @@ class FormalParameterBuilder extends ModifierBuilderImpl
} }
void finalizeInitializingFormal( void finalizeInitializingFormal(
DeclarationBuilder declarationBuilder, ClassHierarchyBase hierarchy) { DeclarationBuilder declarationBuilder,
ConstructorDeclaration constructorDeclaration,
ClassHierarchyBase hierarchy) {
Builder? fieldBuilder = declarationBuilder.lookupLocalMember(name); Builder? fieldBuilder = declarationBuilder.lookupLocalMember(name);
if (fieldBuilder is SourceFieldBuilder) { if (fieldBuilder is SourceFieldBuilder) {
type.registerInferredType(fieldBuilder.inferType(hierarchy)); DartType fieldType = fieldBuilder.inferType(hierarchy);
fieldType = constructorDeclaration.substituteFieldType(fieldType);
type.registerInferredType(fieldType);
} else { } else {
type.registerInferredType(const DynamicType()); type.registerInferredType(const DynamicType());
} }

View file

@ -1887,14 +1887,14 @@ class BodyBuilder extends StackListenerImpl
return arguments; return arguments;
} }
void finishConstructor(ConstructorDeclaration builder, void finishConstructor(ConstructorDeclaration constructorDeclaration,
AsyncMarker asyncModifier, Statement? body, AsyncMarker asyncModifier, Statement? body,
{required List<Object /* Expression | NamedExpression */ >? {required List<Object /* Expression | NamedExpression */ >?
superParametersAsArguments}) { superParametersAsArguments}) {
/// Quotes below are from [Dart Programming Language Specification, 4th /// Quotes below are from [Dart Programming Language Specification, 4th
/// Edition]( /// Edition](
/// https://ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf). /// https://ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf).
assert(builder == this.member); assert(constructorDeclaration == this.member);
assert(() { assert(() {
if (superParametersAsArguments == null) { if (superParametersAsArguments == null) {
return true; return true;
@ -1933,9 +1933,9 @@ class BodyBuilder extends StackListenerImpl
"Expected 'superParametersAsArguments' " "Expected 'superParametersAsArguments' "
"to be sorted by occurrence in file."); "to be sorted by occurrence in file.");
Member member = builder.member; Member member = constructorDeclaration.member;
FunctionNode function = builder.function; FunctionNode function = constructorDeclaration.function;
List<FormalParameterBuilder>? formals = builder.formals; List<FormalParameterBuilder>? formals = constructorDeclaration.formals;
if (formals != null) { if (formals != null) {
for (int i = 0; i < formals.length; i++) { for (int i = 0; i < formals.length; i++) {
FormalParameterBuilder parameter = formals[i]; FormalParameterBuilder parameter = formals[i];
@ -1992,7 +1992,7 @@ class BodyBuilder extends StackListenerImpl
if (initializers.last is SuperInitializer) { if (initializers.last is SuperInitializer) {
SuperInitializer superInitializer = SuperInitializer superInitializer =
initializers.last as SuperInitializer; initializers.last as SuperInitializer;
if (builder.classDeclaration.isEnum) { if (constructorDeclaration.classDeclaration.isEnum) {
initializers[initializers.length - 1] = buildInvalidInitializer( initializers[initializers.length - 1] = buildInvalidInitializer(
buildProblem(fasta.messageEnumConstructorSuperInitializer, buildProblem(fasta.messageEnumConstructorSuperInitializer,
superInitializer.fileOffset, noLength)) superInitializer.fileOffset, noLength))
@ -2054,19 +2054,19 @@ class BodyBuilder extends StackListenerImpl
List<InitializerInferenceResult> inferenceResults = List<InitializerInferenceResult> inferenceResults =
new List<InitializerInferenceResult>.generate( new List<InitializerInferenceResult>.generate(
initializers.length, initializers.length,
(index) => (index) => typeInferrer.inferInitializer(
typeInferrer.inferInitializer(this, initializers[index]), this, constructorDeclaration, initializers[index]),
growable: false); growable: false);
if (!builder.isExternal) { if (!constructorDeclaration.isExternal) {
for (int i = 0; i < initializers.length; i++) { for (int i = 0; i < initializers.length; i++) {
builder.addInitializer(initializers[i], this, constructorDeclaration.addInitializer(initializers[i], this,
inferenceResult: inferenceResults[i]); inferenceResult: inferenceResults[i]);
} }
} }
} }
List<Initializer> builtInitializers = builder.initializers; List<Initializer> builtInitializers = constructorDeclaration.initializers;
if (asyncModifier != AsyncMarker.Sync) { if (asyncModifier != AsyncMarker.Sync) {
builtInitializers.add(buildInvalidInitializer(buildProblem( builtInitializers.add(buildInvalidInitializer(buildProblem(
fasta.messageConstructorNotSync, body!.fileOffset, noLength))); fasta.messageConstructorNotSync, body!.fileOffset, noLength)));
@ -2110,11 +2110,11 @@ class BodyBuilder extends StackListenerImpl
if (superTarget == null || if (superTarget == null ||
checkArgumentsForFunction(superTarget.function, arguments, checkArgumentsForFunction(superTarget.function, arguments,
builder.charOffset, const <TypeParameter>[]) != constructorDeclaration.charOffset, const <TypeParameter>[]) !=
null) { null) {
String superclass = String superclass =
sourceClassBuilder!.supertypeBuilder!.fullNameForErrors; sourceClassBuilder!.supertypeBuilder!.fullNameForErrors;
int length = builder.name.length; int length = constructorDeclaration.name.length;
if (length == 0) { if (length == 0) {
length = sourceClassBuilder!.cls.name.length; length = sourceClassBuilder!.cls.name.length;
} }
@ -2122,17 +2122,17 @@ class BodyBuilder extends StackListenerImpl
buildProblem( buildProblem(
fasta.templateSuperclassHasNoDefaultConstructor fasta.templateSuperclassHasNoDefaultConstructor
.withArguments(superclass), .withArguments(superclass),
builder.charOffset, constructorDeclaration.charOffset,
length), length),
builder.charOffset); constructorDeclaration.charOffset);
} else { } else {
initializer = buildSuperInitializer( initializer = buildSuperInitializer(
true, superTarget, arguments, builder.charOffset); true, superTarget, arguments, constructorDeclaration.charOffset);
} }
if (libraryFeatures.superParameters.isEnabled) { if (libraryFeatures.superParameters.isEnabled) {
InitializerInferenceResult inferenceResult = InitializerInferenceResult inferenceResult = typeInferrer
typeInferrer.inferInitializer(this, initializer); .inferInitializer(this, constructorDeclaration, initializer);
builder.addInitializer(initializer, this, constructorDeclaration.addInitializer(initializer, this,
inferenceResult: inferenceResult); inferenceResult: inferenceResult);
} else { } else {
builtInitializers.add(initializer); builtInitializers.add(initializer);
@ -7895,10 +7895,14 @@ class BodyBuilder extends StackListenerImpl
..fileOffset = assignmentOffset ..fileOffset = assignmentOffset
]; ];
} else { } else {
ConstructorDeclaration constructorBuilder =
member as ConstructorDeclaration;
if (formal != null && formal.type is! OmittedTypeBuilder) { if (formal != null && formal.type is! OmittedTypeBuilder) {
DartType formalType = formal.variable!.type; DartType formalType = formal.variable!.type;
if (!typeEnvironment.isSubtypeOf(formalType, builder.fieldType, DartType fieldType =
SubtypeCheckMode.withNullabilities)) { constructorBuilder.substituteFieldType(builder.fieldType);
if (!typeEnvironment.isSubtypeOf(
formalType, fieldType, SubtypeCheckMode.withNullabilities)) {
libraryBuilder.addProblem( libraryBuilder.addProblem(
fasta.templateInitializingFormalTypeMismatch.withArguments( fasta.templateInitializingFormalTypeMismatch.withArguments(
name, name,
@ -7914,8 +7918,6 @@ class BodyBuilder extends StackListenerImpl
]); ]);
} }
} }
ConstructorDeclaration constructorBuilder =
member as ConstructorDeclaration;
constructorBuilder.registerInitializedField(builder); constructorBuilder.registerInitializedField(builder);
return builder.buildInitializer(assignmentOffset, expression, return builder.buildInitializer(assignmentOffset, expression,
isSynthetic: formal != null); isSynthetic: formal != null);

View file

@ -54,4 +54,12 @@ abstract class ConstructorDeclaration implements SourceFunctionBuilder {
/// [registerInitializedField] and passes on the ownership of the collection /// [registerInitializedField] and passes on the ownership of the collection
/// to the caller. /// to the caller.
Set<SourceFieldBuilder>? takeInitializedFields(); Set<SourceFieldBuilder>? takeInitializedFields();
/// Substitute [fieldType] from the context of the enclosing class or
/// inline class to this constructor.
///
/// This is used for generic inline class constructors where the type
/// variable referring to the class type variables must be substituted for
/// the synthesized constructor type variables.
DartType substituteFieldType(DartType fieldType);
} }

View file

@ -1966,8 +1966,8 @@ class OutlineBuilder extends StackListenerImpl {
break; break;
} }
bool isStatic = (modifiers & staticMask) != 0; bool isStatic = (modifiers & staticMask) != 0;
if (constructorName == null && bool isConstructor = constructorName != null;
!isStatic && if (!isStatic &&
(libraryBuilder.currentTypeParameterScopeBuilder.kind == (libraryBuilder.currentTypeParameterScopeBuilder.kind ==
TypeParameterScopeKind.extensionDeclaration || TypeParameterScopeKind.extensionDeclaration ||
libraryBuilder.currentTypeParameterScopeBuilder.kind == libraryBuilder.currentTypeParameterScopeBuilder.kind ==
@ -1997,53 +1997,56 @@ class OutlineBuilder extends StackListenerImpl {
typeVariables = synthesizedTypeVariables; typeVariables = synthesizedTypeVariables;
} }
} }
List<FormalParameterBuilder> synthesizedFormals = []; if (!isConstructor) {
TypeBuilder thisType; List<FormalParameterBuilder> synthesizedFormals = [];
if (declaration.kind == TypeParameterScopeKind.extensionDeclaration) { TypeBuilder thisType;
thisType = declaration.extensionThisType; if (declaration.kind == TypeParameterScopeKind.extensionDeclaration) {
} else { thisType = declaration.extensionThisType;
thisType = libraryBuilder.addNamedType( } else {
declaration.name, thisType = libraryBuilder.addNamedType(
const NullabilityBuilder.omitted(), declaration.name,
declaration.typeVariables != null const NullabilityBuilder.omitted(),
? new List<TypeBuilder>.generate( declaration.typeVariables != null
declaration.typeVariables!.length, ? new List<TypeBuilder>.generate(
(int index) => declaration.typeVariables!.length,
new NamedTypeBuilder.fromTypeDeclarationBuilder( (int index) =>
typeVariables![index], new NamedTypeBuilder.fromTypeDeclarationBuilder(
const NullabilityBuilder.omitted(), typeVariables![index],
instanceTypeVariableAccess: const NullabilityBuilder.omitted(),
InstanceTypeVariableAccessState.Allowed)) instanceTypeVariableAccess:
: null, InstanceTypeVariableAccessState.Allowed))
charOffset, : null,
instanceTypeVariableAccess: charOffset,
InstanceTypeVariableAccessState.Allowed); instanceTypeVariableAccess:
} InstanceTypeVariableAccessState.Allowed);
if (substitution != null) {
List<NamedTypeBuilder> unboundTypes = [];
List<TypeVariableBuilder> unboundTypeVariables = [];
thisType = substitute(thisType, substitution,
unboundTypes: unboundTypes,
unboundTypeVariables: unboundTypeVariables);
for (NamedTypeBuilder unboundType in unboundTypes) {
declaration.registerUnresolvedNamedType(unboundType);
} }
libraryBuilder.unboundTypeVariables.addAll(unboundTypeVariables); if (substitution != null) {
List<NamedTypeBuilder> unboundTypes = [];
List<TypeVariableBuilder> unboundTypeVariables = [];
thisType = substitute(thisType, substitution,
unboundTypes: unboundTypes,
unboundTypeVariables: unboundTypeVariables);
for (NamedTypeBuilder unboundType in unboundTypes) {
declaration.registerUnresolvedNamedType(unboundType);
}
libraryBuilder.unboundTypeVariables.addAll(unboundTypeVariables);
}
synthesizedFormals.add(new FormalParameterBuilder(
/* metadata = */
null,
FormalParameterKind.requiredPositional,
finalMask,
thisType,
syntheticThisName,
null,
charOffset,
fileUri: uri,
isExtensionThis: true));
if (formals != null) {
synthesizedFormals.addAll(formals);
}
formals = synthesizedFormals;
} }
synthesizedFormals.add(new FormalParameterBuilder(
/* metadata = */ null,
FormalParameterKind.requiredPositional,
finalMask,
thisType,
syntheticThisName,
null,
charOffset,
fileUri: uri,
isExtensionThis: true));
if (formals != null) {
synthesizedFormals.addAll(formals);
}
formals = synthesizedFormals;
} }
declarationBuilder.resolveNamedTypes(typeVariables, libraryBuilder); declarationBuilder.resolveNamedTypes(typeVariables, libraryBuilder);

View file

@ -137,7 +137,8 @@ abstract class AbstractSourceConstructorBuilder
for (FormalParameterBuilder formal in formals!) { for (FormalParameterBuilder formal in formals!) {
if (formal.type is InferableTypeBuilder) { if (formal.type is InferableTypeBuilder) {
if (formal.isInitializingFormal) { if (formal.isInitializingFormal) {
formal.finalizeInitializingFormal(declarationBuilder, hierarchy); formal.finalizeInitializingFormal(
declarationBuilder, this, hierarchy);
} }
} }
} }
@ -903,6 +904,13 @@ class DeclaredSourceConstructorBuilder
} }
} }
} }
@override
DartType substituteFieldType(DartType fieldType) {
// Nothing to do. Regular generative constructors don't have their own
// type variables.
return fieldType;
}
} }
class SyntheticSourceConstructorBuilder extends DillConstructorBuilder class SyntheticSourceConstructorBuilder extends DillConstructorBuilder
@ -1150,8 +1158,8 @@ class SourceInlineClassConstructorBuilder
InlineClass inlineClass = inlineClassBuilder.inlineClass; InlineClass inlineClass = inlineClassBuilder.inlineClass;
List<DartType> typeParameterTypes = <DartType>[]; List<DartType> typeParameterTypes = <DartType>[];
for (int i = 0; i < inlineClass.typeParameters.length; i++) { for (int i = 0; i < function.typeParameters.length; i++) {
TypeParameter typeParameter = inlineClass.typeParameters[i]; TypeParameter typeParameter = function.typeParameters[i];
typeParameterTypes.add( typeParameterTypes.add(
new TypeParameterType.withDefaultNullabilityForLibrary( new TypeParameterType.withDefaultNullabilityForLibrary(
typeParameter, libraryBuilder.library)); typeParameter, libraryBuilder.library));
@ -1166,7 +1174,6 @@ class SourceInlineClassConstructorBuilder
buildFunction(); buildFunction();
_constructor.function.fileOffset = charOpenParenOffset; _constructor.function.fileOffset = charOpenParenOffset;
_constructor.function.fileEndOffset = _constructor.fileEndOffset; _constructor.function.fileEndOffset = _constructor.fileEndOffset;
_constructor.function.typeParameters = const <TypeParameter>[];
_constructor.isConst = isConst; _constructor.isConst = isConst;
_constructor.isExternal = isExternal; _constructor.isExternal = isExternal;
@ -1224,7 +1231,30 @@ class SourceInlineClassConstructorBuilder
@override @override
bool get isEffectivelyRedirecting => isRedirecting; bool get isEffectivelyRedirecting => isRedirecting;
// TODO(johnniwinther): Generate initializers and return statement. Substitution? _substitutionCache;
Substitution get _substitution {
if (typeVariables != null) {
assert(
inlineClassBuilder.typeParameters!.length == typeVariables?.length);
_substitutionCache = Substitution.fromPairs(
inlineClassBuilder.inlineClass.typeParameters,
new List<DartType>.generate(
inlineClassBuilder.typeParameters!.length,
(int index) =>
new TypeParameterType.withDefaultNullabilityForLibrary(
function.typeParameters[index],
libraryBuilder.origin.library)));
} else {
_substitutionCache = Substitution.empty;
}
return _substitutionCache!;
}
@override
DartType substituteFieldType(DartType fieldType) {
return _substitution.substituteType(fieldType);
}
} }
class _InitializerToStatementConverter implements InitializerVisitor<void> { class _InitializerToStatementConverter implements InitializerVisitor<void> {

View file

@ -389,27 +389,7 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl
function.returnType = function.returnType =
returnType.build(libraryBuilder, TypeUse.returnType); returnType.build(libraryBuilder, TypeUse.returnType);
} }
if (isInlineClassInstanceMember && isConstructor) { if (isExtensionInstanceMember || isInlineClassInstanceMember) {
SourceInlineClassBuilder inlineClassBuilder =
parent as SourceInlineClassBuilder;
// TODO(johnniwinther): Support [_thisTypeParameters] for inline class
// constructors.
List<DartType> typeArguments;
if (_thisTypeParameters != null) {
typeArguments = new List<DartType>.generate(
_thisTypeParameters!.length,
(int index) => new TypeParameterType(
_thisTypeParameters![index],
TypeParameterType.computeNullabilityFromBound(
_thisTypeParameters![index])));
} else {
typeArguments = [];
}
_thisVariable = new VariableDeclarationImpl(syntheticThisName,
isFinal: true,
type: new InlineType(inlineClassBuilder.inlineClass,
libraryBuilder.nonNullable, typeArguments));
} else if (isExtensionInstanceMember || isInlineClassInstanceMember) {
SourceDeclarationBuilderMixin declarationBuilder = SourceDeclarationBuilderMixin declarationBuilder =
parent as SourceDeclarationBuilderMixin; parent as SourceDeclarationBuilderMixin;
if (declarationBuilder.typeParameters != null) { if (declarationBuilder.typeParameters != null) {
@ -418,7 +398,27 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl
count, (int index) => function.typeParameters[index], count, (int index) => function.typeParameters[index],
growable: false); growable: false);
} }
_thisVariable = function.positionalParameters.first; if (isInlineClassInstanceMember && isConstructor) {
SourceInlineClassBuilder inlineClassBuilder =
parent as SourceInlineClassBuilder;
List<DartType> typeArguments;
if (_thisTypeParameters != null) {
typeArguments = new List<DartType>.generate(
_thisTypeParameters!.length,
(int index) => new TypeParameterType(
_thisTypeParameters![index],
TypeParameterType.computeNullabilityFromBound(
_thisTypeParameters![index])));
} else {
typeArguments = [];
}
_thisVariable = new VariableDeclarationImpl(syntheticThisName,
isFinal: true,
type: new InlineType(inlineClassBuilder.inlineClass,
libraryBuilder.nonNullable, typeArguments));
} else {
_thisVariable = function.positionalParameters.first;
}
} }
} }

View file

@ -42,6 +42,7 @@ import '../kernel/internal_ast.dart';
import '../kernel/late_lowering.dart' as late_lowering; import '../kernel/late_lowering.dart' as late_lowering;
import '../names.dart'; import '../names.dart';
import '../problems.dart' show unhandled; import '../problems.dart' show unhandled;
import '../source/constructor_declaration.dart';
import '../source/source_library_builder.dart'; import '../source/source_library_builder.dart';
import '../uri_offset.dart'; import '../uri_offset.dart';
import 'closure_context.dart'; import 'closure_context.dart';
@ -128,12 +129,14 @@ class InferenceVisitorImpl extends InferenceVisitorBase
@override @override
final TypeAnalyzerOptions options; final TypeAnalyzerOptions options;
final ConstructorDeclaration? constructorDeclaration;
@override @override
late final SharedTypeAnalyzerErrors errors = new SharedTypeAnalyzerErrors( late final SharedTypeAnalyzerErrors errors = new SharedTypeAnalyzerErrors(
helper: helper, uriForInstrumentation: uriForInstrumentation); helper: helper, uriForInstrumentation: uriForInstrumentation);
InferenceVisitorImpl( InferenceVisitorImpl(TypeInferrerImpl inferrer, InferenceHelper helper,
TypeInferrerImpl inferrer, InferenceHelper helper, this.operations) this.constructorDeclaration, this.operations)
: options = new TypeAnalyzerOptions( : options = new TypeAnalyzerOptions(
nullSafetyEnabled: inferrer.libraryBuilder.isNonNullableByDefault, nullSafetyEnabled: inferrer.libraryBuilder.isNonNullableByDefault,
patternsEnabled: false), patternsEnabled: false),
@ -1301,10 +1304,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
@override @override
InitializerInferenceResult visitFieldInitializer(FieldInitializer node) { InitializerInferenceResult visitFieldInitializer(FieldInitializer node) {
DartType fieldType = node.field.type;
fieldType = constructorDeclaration!.substituteFieldType(fieldType);
ExpressionInferenceResult initializerResult = ExpressionInferenceResult initializerResult =
inferExpression(node.value, node.field.type); inferExpression(node.value, fieldType);
Expression initializer = ensureAssignableResult( Expression initializer = ensureAssignableResult(
node.field.type, initializerResult, fieldType, initializerResult,
fileOffset: node.fileOffset) fileOffset: node.fileOffset)
.expression; .expression;
node.value = initializer..parent = node; node.value = initializer..parent = node;

View file

@ -9,6 +9,7 @@ import 'package:kernel/ast.dart';
import '../../base/instrumentation.dart' show Instrumentation; import '../../base/instrumentation.dart' show Instrumentation;
import '../kernel/benchmarker.dart' show BenchmarkSubdivides, Benchmarker; import '../kernel/benchmarker.dart' show BenchmarkSubdivides, Benchmarker;
import '../kernel/internal_ast.dart'; import '../kernel/internal_ast.dart';
import '../source/constructor_declaration.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder; import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import 'closure_context.dart'; import 'closure_context.dart';
import 'inference_helper.dart' show InferenceHelper; import 'inference_helper.dart' show InferenceHelper;
@ -59,8 +60,8 @@ abstract class TypeInferrer {
DartType returnType, AsyncMarker asyncMarker, Statement body); DartType returnType, AsyncMarker asyncMarker, Statement body);
/// Performs type inference on the given constructor initializer. /// Performs type inference on the given constructor initializer.
InitializerInferenceResult inferInitializer( InitializerInferenceResult inferInitializer(InferenceHelper helper,
InferenceHelper helper, Initializer initializer); ConstructorDeclaration constructorDeclaration, Initializer initializer);
/// Performs type inference on the given metadata annotations. /// Performs type inference on the given metadata annotations.
void inferMetadata( void inferMetadata(
@ -144,10 +145,12 @@ class TypeInferrerImpl implements TypeInferrer {
unpromotablePrivateFieldNames: unpromotablePrivateFieldNames:
libraryBuilder.unpromotablePrivateFieldNames); libraryBuilder.unpromotablePrivateFieldNames);
InferenceVisitorBase _createInferenceVisitor(InferenceHelper helper) { InferenceVisitorBase _createInferenceVisitor(InferenceHelper helper,
[ConstructorDeclaration? constructorDeclaration]) {
// For full (non-top level) inference, we need access to the // For full (non-top level) inference, we need access to the
// InferenceHelper so that we can perform error reporting. // InferenceHelper so that we can perform error reporting.
return new InferenceVisitorImpl(this, helper, operations); return new InferenceVisitorImpl(
this, helper, constructorDeclaration, operations);
} }
@override @override
@ -244,14 +247,15 @@ class TypeInferrerImpl implements TypeInferrer {
} }
@override @override
InitializerInferenceResult inferInitializer( InitializerInferenceResult inferInitializer(InferenceHelper helper,
InferenceHelper helper, Initializer initializer) { ConstructorDeclaration constructorDeclaration, Initializer initializer) {
// Use polymorphic dispatch on [KernelInitializer] to perform whatever // Use polymorphic dispatch on [KernelInitializer] to perform whatever
// kind of type inference is correct for this kind of initializer. // kind of type inference is correct for this kind of initializer.
// TODO(paulberry): experiment to see if dynamic dispatch would be better, // TODO(paulberry): experiment to see if dynamic dispatch would be better,
// so that the type hierarchy will be simpler (which may speed up "is" // so that the type hierarchy will be simpler (which may speed up "is"
// checks). // checks).
InferenceVisitorBase visitor = _createInferenceVisitor(helper); InferenceVisitorBase visitor =
_createInferenceVisitor(helper, constructorDeclaration);
InitializerInferenceResult result = visitor.inferInitializer(initializer); InitializerInferenceResult result = visitor.inferInitializer(initializer);
visitor.checkCleanState(); visitor.checkCleanState();
return result; return result;
@ -356,11 +360,11 @@ class TypeInferrerImplBenchmarked implements TypeInferrer {
} }
@override @override
InitializerInferenceResult inferInitializer( InitializerInferenceResult inferInitializer(InferenceHelper helper,
InferenceHelper helper, Initializer initializer) { ConstructorDeclaration constructorDeclaration, Initializer initializer) {
benchmarker.beginSubdivide(BenchmarkSubdivides.inferInitializer); benchmarker.beginSubdivide(BenchmarkSubdivides.inferInitializer);
InitializerInferenceResult result = InitializerInferenceResult result =
impl.inferInitializer(helper, initializer); impl.inferInitializer(helper, constructorDeclaration, initializer);
benchmarker.endSubdivide(); benchmarker.endSubdivide();
return result; return result;
} }

View file

@ -9,7 +9,7 @@ inline class Class1 {
Class1.named1(this.it, int additional); Class1.named1(this.it, int additional);
Class1.named2(this.it, int additional) { Class1.named2(int this.it, int additional) {
print(additional); print(additional);
} }
@ -24,7 +24,6 @@ inline class Class1 {
Class1.named6(String text) : it = text.length; Class1.named6(String text) : it = text.length;
} }
/* TODO(johnniwinther): Support generic inline class constructors.
inline class Class2<T> { inline class Class2<T> {
final T it; final T it;
@ -32,7 +31,7 @@ inline class Class2<T> {
Class2.named1(this.it, int additional); Class2.named1(this.it, int additional);
Class2.named2(this.it, int additional) { Class2.named2(T this.it, int additional) {
print(additional); print(additional);
} }
@ -45,4 +44,4 @@ inline class Class2<T> {
} }
Class2.named6(List<T> list) : it = list.first; Class2.named6(List<T> list) : it = list.first;
}*/ }

View file

@ -11,6 +11,15 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor named5 = self::Class1|named5; constructor named5 = self::Class1|named5;
constructor named6 = self::Class1|named6; constructor named6 = self::Class1|named6;
} }
inline class Class2<T extends core::Object? = dynamic> /* declaredRepresentationType = T% */ {
constructor • = self::Class2|;
constructor named1 = self::Class2|named1;
constructor named2 = self::Class2|named2;
constructor named3 = self::Class2|named3;
constructor named4 = self::Class2|named4;
constructor named5 = self::Class2|named5;
constructor named6 = self::Class2|named6;
}
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int}; final self::Class1 #this = text.{core::String::length}{core::int};
return #this; return #this;
} }
method Class2|<T extends core::Object? = dynamic>(self::Class2|::T% it) → self::Class2<self::Class2|::T%> {
final self::Class2<self::Class2|::T%> #this = it;
return #this;
}
method Class2|named1<T extends core::Object? = dynamic>(self::Class2|named1::T% it, core::int additional) → self::Class2<self::Class2|named1::T%> {
final self::Class2<self::Class2|named1::T%> #this = it;
return #this;
}
method Class2|named2<T extends core::Object? = dynamic>(self::Class2|named2::T% it, core::int additional) → self::Class2<self::Class2|named2::T%> {
final self::Class2<self::Class2|named2::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named3<T extends core::Object? = dynamic>(self::Class2|named3::T% it) → self::Class2<self::Class2|named3::T%> {
final self::Class2<self::Class2|named3::T%> #this = it;
return #this;
}
method Class2|named4<T extends core::Object? = dynamic>(core::int additional, self::Class2|named4::T% it) → self::Class2<self::Class2|named4::T%> {
final self::Class2<self::Class2|named4::T%> #this = it;
return #this;
}
method Class2|named5<T extends core::Object? = dynamic>(core::int additional, self::Class2|named5::T% it) → self::Class2<self::Class2|named5::T%> {
final self::Class2<self::Class2|named5::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named6<T extends core::Object? = dynamic>(core::List<self::Class2|named6::T%> list) → self::Class2<self::Class2|named6::T%> {
final self::Class2<self::Class2|named6::T%> #this = list.{core::Iterable::first}{self::Class2|named6::T%};
return #this;
}

View file

@ -11,6 +11,15 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor named5 = self::Class1|named5; constructor named5 = self::Class1|named5;
constructor named6 = self::Class1|named6; constructor named6 = self::Class1|named6;
} }
inline class Class2<T extends core::Object? = dynamic> /* declaredRepresentationType = T% */ {
constructor • = self::Class2|;
constructor named1 = self::Class2|named1;
constructor named2 = self::Class2|named2;
constructor named3 = self::Class2|named3;
constructor named4 = self::Class2|named4;
constructor named5 = self::Class2|named5;
constructor named6 = self::Class2|named6;
}
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int}; final self::Class1 #this = text.{core::String::length}{core::int};
return #this; return #this;
} }
method Class2|<T extends core::Object? = dynamic>(self::Class2|::T% it) → self::Class2<self::Class2|::T%> {
final self::Class2<self::Class2|::T%> #this = it;
return #this;
}
method Class2|named1<T extends core::Object? = dynamic>(self::Class2|named1::T% it, core::int additional) → self::Class2<self::Class2|named1::T%> {
final self::Class2<self::Class2|named1::T%> #this = it;
return #this;
}
method Class2|named2<T extends core::Object? = dynamic>(self::Class2|named2::T% it, core::int additional) → self::Class2<self::Class2|named2::T%> {
final self::Class2<self::Class2|named2::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named3<T extends core::Object? = dynamic>(self::Class2|named3::T% it) → self::Class2<self::Class2|named3::T%> {
final self::Class2<self::Class2|named3::T%> #this = it;
return #this;
}
method Class2|named4<T extends core::Object? = dynamic>(core::int additional, self::Class2|named4::T% it) → self::Class2<self::Class2|named4::T%> {
final self::Class2<self::Class2|named4::T%> #this = it;
return #this;
}
method Class2|named5<T extends core::Object? = dynamic>(core::int additional, self::Class2|named5::T% it) → self::Class2<self::Class2|named5::T%> {
final self::Class2<self::Class2|named5::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named6<T extends core::Object? = dynamic>(core::List<self::Class2|named6::T%> list) → self::Class2<self::Class2|named6::T%> {
final self::Class2<self::Class2|named6::T%> #this = list.{core::Iterable::first}{self::Class2|named6::T%};
return #this;
}

View file

@ -3,9 +3,20 @@ class Class1 {
final int it; final int it;
Class1(this.it); Class1(this.it);
Class1.named1(this.it, int additional); Class1.named1(this.it, int additional);
Class1.named2(this.it, int additional) {} Class1.named2(int this.it, int additional) {}
Class1.named3(int it) : this.it = it; Class1.named3(int it) : this.it = it;
Class1.named4(int additional, int it) : this.it = it; Class1.named4(int additional, int it) : this.it = it;
Class1.named5(int additional, int it) : this.it = it {} Class1.named5(int additional, int it) : this.it = it {}
Class1.named6(String text) : it = text.length; Class1.named6(String text) : it = text.length;
} }
inline
class Class2<T> {
final T it;
Class2(this.it);
Class2.named1(this.it, int additional);
Class2.named2(T this.it, int additional) {}
Class2.named3(T it) : this.it = it;
Class2.named4(int additional, T it) : this.it = it;
Class2.named5(int additional, T it) : this.it = it {}
Class2.named6(List<T> list) : it = list.first;
}

View file

@ -11,6 +11,15 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor named5 = self::Class1|named5; constructor named5 = self::Class1|named5;
constructor named6 = self::Class1|named6; constructor named6 = self::Class1|named6;
} }
inline class Class2<T extends core::Object? = dynamic> /* declaredRepresentationType = T% */ {
constructor • = self::Class2|;
constructor named1 = self::Class2|named1;
constructor named2 = self::Class2|named2;
constructor named3 = self::Class2|named3;
constructor named4 = self::Class2|named4;
constructor named5 = self::Class2|named5;
constructor named6 = self::Class2|named6;
}
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int}; final self::Class1 #this = text.{core::String::length}{core::int};
return #this; return #this;
} }
method Class2|<T extends core::Object? = dynamic>(self::Class2|::T% it) → self::Class2<self::Class2|::T%> {
final self::Class2<self::Class2|::T%> #this = it;
return #this;
}
method Class2|named1<T extends core::Object? = dynamic>(self::Class2|named1::T% it, core::int additional) → self::Class2<self::Class2|named1::T%> {
final self::Class2<self::Class2|named1::T%> #this = it;
return #this;
}
method Class2|named2<T extends core::Object? = dynamic>(self::Class2|named2::T% it, core::int additional) → self::Class2<self::Class2|named2::T%> {
final self::Class2<self::Class2|named2::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named3<T extends core::Object? = dynamic>(self::Class2|named3::T% it) → self::Class2<self::Class2|named3::T%> {
final self::Class2<self::Class2|named3::T%> #this = it;
return #this;
}
method Class2|named4<T extends core::Object? = dynamic>(core::int additional, self::Class2|named4::T% it) → self::Class2<self::Class2|named4::T%> {
final self::Class2<self::Class2|named4::T%> #this = it;
return #this;
}
method Class2|named5<T extends core::Object? = dynamic>(core::int additional, self::Class2|named5::T% it) → self::Class2<self::Class2|named5::T%> {
final self::Class2<self::Class2|named5::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named6<T extends core::Object? = dynamic>(core::List<self::Class2|named6::T%> list) → self::Class2<self::Class2|named6::T%> {
final self::Class2<self::Class2|named6::T%> #this = list.{core::Iterable::first}{self::Class2|named6::T%};
return #this;
}

View file

@ -11,6 +11,15 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor named5 = self::Class1|named5; constructor named5 = self::Class1|named5;
constructor named6 = self::Class1|named6; constructor named6 = self::Class1|named6;
} }
inline class Class2<T extends core::Object? = dynamic> /* declaredRepresentationType = T% */ {
constructor • = self::Class2|;
constructor named1 = self::Class2|named1;
constructor named2 = self::Class2|named2;
constructor named3 = self::Class2|named3;
constructor named4 = self::Class2|named4;
constructor named5 = self::Class2|named5;
constructor named6 = self::Class2|named6;
}
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int}; final self::Class1 #this = text.{core::String::length}{core::int};
return #this; return #this;
} }
method Class2|<T extends core::Object? = dynamic>(self::Class2|::T% it) → self::Class2<self::Class2|::T%> {
final self::Class2<self::Class2|::T%> #this = it;
return #this;
}
method Class2|named1<T extends core::Object? = dynamic>(self::Class2|named1::T% it, core::int additional) → self::Class2<self::Class2|named1::T%> {
final self::Class2<self::Class2|named1::T%> #this = it;
return #this;
}
method Class2|named2<T extends core::Object? = dynamic>(self::Class2|named2::T% it, core::int additional) → self::Class2<self::Class2|named2::T%> {
final self::Class2<self::Class2|named2::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named3<T extends core::Object? = dynamic>(self::Class2|named3::T% it) → self::Class2<self::Class2|named3::T%> {
final self::Class2<self::Class2|named3::T%> #this = it;
return #this;
}
method Class2|named4<T extends core::Object? = dynamic>(core::int additional, self::Class2|named4::T% it) → self::Class2<self::Class2|named4::T%> {
final self::Class2<self::Class2|named4::T%> #this = it;
return #this;
}
method Class2|named5<T extends core::Object? = dynamic>(core::int additional, self::Class2|named5::T% it) → self::Class2<self::Class2|named5::T%> {
final self::Class2<self::Class2|named5::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named6<T extends core::Object? = dynamic>(core::List<self::Class2|named6::T%> list) → self::Class2<self::Class2|named6::T%> {
final self::Class2<self::Class2|named6::T%> #this = list.{core::Iterable::first}{self::Class2|named6::T%};
return #this;
}

View file

@ -11,6 +11,15 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor named5 = self::Class1|named5; constructor named5 = self::Class1|named5;
constructor named6 = self::Class1|named6; constructor named6 = self::Class1|named6;
} }
inline class Class2<T extends core::Object? = dynamic> /* declaredRepresentationType = T% */ {
constructor • = self::Class2|;
constructor named1 = self::Class2|named1;
constructor named2 = self::Class2|named2;
constructor named3 = self::Class2|named3;
constructor named4 = self::Class2|named4;
constructor named5 = self::Class2|named5;
constructor named6 = self::Class2|named6;
}
method Class1|(core::int it) → self::Class1 method Class1|(core::int it) → self::Class1
; ;
method Class1|named1(core::int it, core::int additional) → self::Class1 method Class1|named1(core::int it, core::int additional) → self::Class1
@ -25,3 +34,17 @@ method Class1|named5(core::int additional, core::int it) → self::Class1
; ;
method Class1|named6(core::String text) → self::Class1 method Class1|named6(core::String text) → self::Class1
; ;
method Class2|<T extends core::Object? = dynamic>(self::Class2|::T% it) → self::Class2<self::Class2|::T%>
;
method Class2|named1<T extends core::Object? = dynamic>(self::Class2|named1::T% it, core::int additional) → self::Class2<self::Class2|named1::T%>
;
method Class2|named2<T extends core::Object? = dynamic>(self::Class2|named2::T% it, core::int additional) → self::Class2<self::Class2|named2::T%>
;
method Class2|named3<T extends core::Object? = dynamic>(self::Class2|named3::T% it) → self::Class2<self::Class2|named3::T%>
;
method Class2|named4<T extends core::Object? = dynamic>(core::int additional, self::Class2|named4::T% it) → self::Class2<self::Class2|named4::T%>
;
method Class2|named5<T extends core::Object? = dynamic>(core::int additional, self::Class2|named5::T% it) → self::Class2<self::Class2|named5::T%>
;
method Class2|named6<T extends core::Object? = dynamic>(core::List<self::Class2|named6::T%> list) → self::Class2<self::Class2|named6::T%>
;

View file

@ -11,6 +11,15 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor named5 = self::Class1|named5; constructor named5 = self::Class1|named5;
constructor named6 = self::Class1|named6; constructor named6 = self::Class1|named6;
} }
inline class Class2<T extends core::Object? = dynamic> /* declaredRepresentationType = T% */ {
constructor • = self::Class2|;
constructor named1 = self::Class2|named1;
constructor named2 = self::Class2|named2;
constructor named3 = self::Class2|named3;
constructor named4 = self::Class2|named4;
constructor named5 = self::Class2|named5;
constructor named6 = self::Class2|named6;
}
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int}; final self::Class1 #this = text.{core::String::length}{core::int};
return #this; return #this;
} }
method Class2|<T extends core::Object? = dynamic>(self::Class2|::T% it) → self::Class2<self::Class2|::T%> {
final self::Class2<self::Class2|::T%> #this = it;
return #this;
}
method Class2|named1<T extends core::Object? = dynamic>(self::Class2|named1::T% it, core::int additional) → self::Class2<self::Class2|named1::T%> {
final self::Class2<self::Class2|named1::T%> #this = it;
return #this;
}
method Class2|named2<T extends core::Object? = dynamic>(self::Class2|named2::T% it, core::int additional) → self::Class2<self::Class2|named2::T%> {
final self::Class2<self::Class2|named2::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named3<T extends core::Object? = dynamic>(self::Class2|named3::T% it) → self::Class2<self::Class2|named3::T%> {
final self::Class2<self::Class2|named3::T%> #this = it;
return #this;
}
method Class2|named4<T extends core::Object? = dynamic>(core::int additional, self::Class2|named4::T% it) → self::Class2<self::Class2|named4::T%> {
final self::Class2<self::Class2|named4::T%> #this = it;
return #this;
}
method Class2|named5<T extends core::Object? = dynamic>(core::int additional, self::Class2|named5::T% it) → self::Class2<self::Class2|named5::T%> {
final self::Class2<self::Class2|named5::T%> #this = it;
{
core::print(additional);
}
return #this;
}
method Class2|named6<T extends core::Object? = dynamic>(core::List<self::Class2|named6::T%> list) → self::Class2<self::Class2|named6::T%> {
final self::Class2<self::Class2|named6::T%> #this = list.{core::Iterable::first}{self::Class2|named6::T%};
return #this;
}

View file

@ -11,7 +11,8 @@ inline class Class1 {
inline class Class2 = Object with Mixin; inline class Class2 = Object with Mixin;
inline class Class3<T> { inline class Class3<T> {
final List<T> it; final List<T> it;
// TODO(johnniwinther): Support generic inline class constructor.
Class3(this.it);
} }
method(Class1 c1, Class3<int> c3) {} method(Class1 c1, Class3<int> c3) {}

View file

@ -1,12 +1,4 @@
library /*isNonNullableByDefault*/; library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/inline_class/inline_class_declaration.dart:13:17: Error: Final field 'it' is not initialized.
// Try to initialize the field in the declaration or in every constructor.
// final List<T> it;
// ^^
//
import self as self; import self as self;
import "dart:core" as core; import "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|; constructor • = self::Class1|;
} }
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ { inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
} }
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
} }
method Class3|<T extends core::Object? = dynamic>(core::List<self::Class3|::T%> it) → self::Class3<self::Class3|::T%> {
final self::Class3<self::Class3|::T%> #this = it;
return #this;
}
static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {} static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {}

View file

@ -1,12 +1,4 @@
library /*isNonNullableByDefault*/; library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/inline_class/inline_class_declaration.dart:13:17: Error: Final field 'it' is not initialized.
// Try to initialize the field in the declaration or in every constructor.
// final List<T> it;
// ^^
//
import self as self; import self as self;
import "dart:core" as core; import "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|; constructor • = self::Class1|;
} }
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ { inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
} }
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
} }
method Class3|<T extends core::Object? = dynamic>(core::List<self::Class3|::T%> it) → self::Class3<self::Class3|::T%> {
final self::Class3<self::Class3|::T%> #this = it;
return #this;
}
static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {} static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {}

View file

@ -9,5 +9,6 @@ class Class2 = Object with Mixin;
inline inline
class Class3<T> { class Class3<T> {
final List<T> it; final List<T> it;
Class3(this.it);
} }
method(Class1 c1, Class3<int> c3) {} method(Class1 c1, Class3<int> c3) {}

View file

@ -1,12 +1,4 @@
library /*isNonNullableByDefault*/; library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/inline_class/inline_class_declaration.dart:13:17: Error: Final field 'it' is not initialized.
// Try to initialize the field in the declaration or in every constructor.
// final List<T> it;
// ^^
//
import self as self; import self as self;
import "dart:core" as core; import "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|; constructor • = self::Class1|;
} }
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ { inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
} }
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
} }
method Class3|<T extends core::Object? = dynamic>(core::List<self::Class3|::T%> it) → self::Class3<self::Class3|::T%> {
final self::Class3<self::Class3|::T%> #this = it;
return #this;
}
static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {} static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {}

View file

@ -1,12 +1,4 @@
library /*isNonNullableByDefault*/; library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/inline_class/inline_class_declaration.dart:13:17: Error: Final field 'it' is not initialized.
// Try to initialize the field in the declaration or in every constructor.
// final List<T> it;
// ^^
//
import self as self; import self as self;
import "dart:core" as core; import "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|; constructor • = self::Class1|;
} }
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ { inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
} }
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
} }
method Class3|<T extends core::Object? = dynamic>(core::List<self::Class3|::T%> it) → self::Class3<self::Class3|::T%> {
final self::Class3<self::Class3|::T%> #this = it;
return #this;
}
static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {} static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {}

View file

@ -13,8 +13,11 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|; constructor • = self::Class1|;
} }
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ { inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
} }
method Class1|(core::int it) → self::Class1 method Class1|(core::int it) → self::Class1
; ;
method Class3|<T extends core::Object? = dynamic>(core::List<self::Class3|::T%> it) → self::Class3<self::Class3|::T%>
;
static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic
; ;

View file

@ -1,12 +1,4 @@
library /*isNonNullableByDefault*/; library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/inline_class/inline_class_declaration.dart:13:17: Error: Final field 'it' is not initialized.
// Try to initialize the field in the declaration or in every constructor.
// final List<T> it;
// ^^
//
import self as self; import self as self;
import "dart:core" as core; import "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|; constructor • = self::Class1|;
} }
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ { inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
} }
method Class1|(core::int it) → self::Class1 { method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it; final self::Class1 #this = it;
return #this; return #this;
} }
method Class3|<T extends core::Object? = dynamic>(core::List<self::Class3|::T%> it) → self::Class3<self::Class3|::T%> {
final self::Class3<self::Class3|::T%> #this = it;
return #this;
}
static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {} static method method(self::Class1 c1, self::Class3<core::int> c3) → dynamic {}