[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'
show FormalParameterKind, FormalParameterKindExtension;
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'
show DartType, DynamicType, Expression, NullLiteral, VariableDeclaration;
import 'package:kernel/class_hierarchy.dart';
@ -221,10 +222,14 @@ class FormalParameterBuilder extends ModifierBuilderImpl
}
void finalizeInitializingFormal(
DeclarationBuilder declarationBuilder, ClassHierarchyBase hierarchy) {
DeclarationBuilder declarationBuilder,
ConstructorDeclaration constructorDeclaration,
ClassHierarchyBase hierarchy) {
Builder? fieldBuilder = declarationBuilder.lookupLocalMember(name);
if (fieldBuilder is SourceFieldBuilder) {
type.registerInferredType(fieldBuilder.inferType(hierarchy));
DartType fieldType = fieldBuilder.inferType(hierarchy);
fieldType = constructorDeclaration.substituteFieldType(fieldType);
type.registerInferredType(fieldType);
} else {
type.registerInferredType(const DynamicType());
}

View file

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

View file

@ -54,4 +54,12 @@ abstract class ConstructorDeclaration implements SourceFunctionBuilder {
/// [registerInitializedField] and passes on the ownership of the collection
/// to the caller.
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;
}
bool isStatic = (modifiers & staticMask) != 0;
if (constructorName == null &&
!isStatic &&
bool isConstructor = constructorName != null;
if (!isStatic &&
(libraryBuilder.currentTypeParameterScopeBuilder.kind ==
TypeParameterScopeKind.extensionDeclaration ||
libraryBuilder.currentTypeParameterScopeBuilder.kind ==
@ -1997,53 +1997,56 @@ class OutlineBuilder extends StackListenerImpl {
typeVariables = synthesizedTypeVariables;
}
}
List<FormalParameterBuilder> synthesizedFormals = [];
TypeBuilder thisType;
if (declaration.kind == TypeParameterScopeKind.extensionDeclaration) {
thisType = declaration.extensionThisType;
} else {
thisType = libraryBuilder.addNamedType(
declaration.name,
const NullabilityBuilder.omitted(),
declaration.typeVariables != null
? new List<TypeBuilder>.generate(
declaration.typeVariables!.length,
(int index) =>
new NamedTypeBuilder.fromTypeDeclarationBuilder(
typeVariables![index],
const NullabilityBuilder.omitted(),
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed))
: null,
charOffset,
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);
if (!isConstructor) {
List<FormalParameterBuilder> synthesizedFormals = [];
TypeBuilder thisType;
if (declaration.kind == TypeParameterScopeKind.extensionDeclaration) {
thisType = declaration.extensionThisType;
} else {
thisType = libraryBuilder.addNamedType(
declaration.name,
const NullabilityBuilder.omitted(),
declaration.typeVariables != null
? new List<TypeBuilder>.generate(
declaration.typeVariables!.length,
(int index) =>
new NamedTypeBuilder.fromTypeDeclarationBuilder(
typeVariables![index],
const NullabilityBuilder.omitted(),
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed))
: null,
charOffset,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
}
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);

View file

@ -137,7 +137,8 @@ abstract class AbstractSourceConstructorBuilder
for (FormalParameterBuilder formal in formals!) {
if (formal.type is InferableTypeBuilder) {
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
@ -1150,8 +1158,8 @@ class SourceInlineClassConstructorBuilder
InlineClass inlineClass = inlineClassBuilder.inlineClass;
List<DartType> typeParameterTypes = <DartType>[];
for (int i = 0; i < inlineClass.typeParameters.length; i++) {
TypeParameter typeParameter = inlineClass.typeParameters[i];
for (int i = 0; i < function.typeParameters.length; i++) {
TypeParameter typeParameter = function.typeParameters[i];
typeParameterTypes.add(
new TypeParameterType.withDefaultNullabilityForLibrary(
typeParameter, libraryBuilder.library));
@ -1166,7 +1174,6 @@ class SourceInlineClassConstructorBuilder
buildFunction();
_constructor.function.fileOffset = charOpenParenOffset;
_constructor.function.fileEndOffset = _constructor.fileEndOffset;
_constructor.function.typeParameters = const <TypeParameter>[];
_constructor.isConst = isConst;
_constructor.isExternal = isExternal;
@ -1224,7 +1231,30 @@ class SourceInlineClassConstructorBuilder
@override
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> {

View file

@ -389,27 +389,7 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl
function.returnType =
returnType.build(libraryBuilder, TypeUse.returnType);
}
if (isInlineClassInstanceMember && isConstructor) {
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) {
if (isExtensionInstanceMember || isInlineClassInstanceMember) {
SourceDeclarationBuilderMixin declarationBuilder =
parent as SourceDeclarationBuilderMixin;
if (declarationBuilder.typeParameters != null) {
@ -418,7 +398,27 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl
count, (int index) => function.typeParameters[index],
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 '../names.dart';
import '../problems.dart' show unhandled;
import '../source/constructor_declaration.dart';
import '../source/source_library_builder.dart';
import '../uri_offset.dart';
import 'closure_context.dart';
@ -128,12 +129,14 @@ class InferenceVisitorImpl extends InferenceVisitorBase
@override
final TypeAnalyzerOptions options;
final ConstructorDeclaration? constructorDeclaration;
@override
late final SharedTypeAnalyzerErrors errors = new SharedTypeAnalyzerErrors(
helper: helper, uriForInstrumentation: uriForInstrumentation);
InferenceVisitorImpl(
TypeInferrerImpl inferrer, InferenceHelper helper, this.operations)
InferenceVisitorImpl(TypeInferrerImpl inferrer, InferenceHelper helper,
this.constructorDeclaration, this.operations)
: options = new TypeAnalyzerOptions(
nullSafetyEnabled: inferrer.libraryBuilder.isNonNullableByDefault,
patternsEnabled: false),
@ -1301,10 +1304,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
@override
InitializerInferenceResult visitFieldInitializer(FieldInitializer node) {
DartType fieldType = node.field.type;
fieldType = constructorDeclaration!.substituteFieldType(fieldType);
ExpressionInferenceResult initializerResult =
inferExpression(node.value, node.field.type);
inferExpression(node.value, fieldType);
Expression initializer = ensureAssignableResult(
node.field.type, initializerResult,
fieldType, initializerResult,
fileOffset: node.fileOffset)
.expression;
node.value = initializer..parent = node;

View file

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

View file

@ -9,7 +9,7 @@ inline class Class1 {
Class1.named1(this.it, int additional);
Class1.named2(this.it, int additional) {
Class1.named2(int this.it, int additional) {
print(additional);
}
@ -24,7 +24,6 @@ inline class Class1 {
Class1.named6(String text) : it = text.length;
}
/* TODO(johnniwinther): Support generic inline class constructors.
inline class Class2<T> {
final T it;
@ -32,7 +31,7 @@ inline class Class2<T> {
Class2.named1(this.it, int additional);
Class2.named2(this.it, int additional) {
Class2.named2(T this.it, int additional) {
print(additional);
}
@ -45,4 +44,4 @@ inline class Class2<T> {
}
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 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 {
final self::Class1 #this = it;
return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int};
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 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 {
final self::Class1 #this = it;
return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int};
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;
Class1(this.it);
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.named4(int additional, int it) : this.it = it;
Class1.named5(int additional, int it) : this.it = it {}
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 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 {
final self::Class1 #this = it;
return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int};
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 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 {
final self::Class1 #this = it;
return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int};
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 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|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 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 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 {
final self::Class1 #this = it;
return #this;
@ -45,3 +54,37 @@ method Class1|named6(core::String text) → self::Class1 {
final self::Class1 #this = text.{core::String::length}{core::int};
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 Class3<T> {
final List<T> it;
// TODO(johnniwinther): Support generic inline class constructor.
Class3(this.it);
}
method(Class1 c1, Class3<int> c3) {}

View file

@ -1,12 +1,4 @@
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 "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|;
}
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
}
method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it;
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 {}

View file

@ -1,12 +1,4 @@
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 "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|;
}
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
}
method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it;
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 {}

View file

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

View file

@ -1,12 +1,4 @@
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 "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|;
}
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
}
method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it;
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 {}

View file

@ -1,12 +1,4 @@
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 "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|;
}
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
}
method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it;
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 {}

View file

@ -13,8 +13,11 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|;
}
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
}
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
;

View file

@ -1,12 +1,4 @@
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 "dart:core" as core;
@ -21,9 +13,14 @@ inline class Class1 /* declaredRepresentationType = core::int */ {
constructor • = self::Class1|;
}
inline class Class3<T extends core::Object? = dynamic> /* declaredRepresentationType = core::List<T%> */ {
constructor • = self::Class3|;
}
method Class1|(core::int it) → self::Class1 {
final self::Class1 #this = it;
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 {}