Skip to content

Commit 3f90ef6

Browse files
johnniwintherCommit Queue
authored andcommitted
[cfe] Add _ImplicitType to handle field and enum element inference
Change-Id: I00bb0817c6504de0f970d58abfaac294c16209e9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/405003 Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 39d2653 commit 3f90ef6

File tree

5 files changed

+180
-164
lines changed

5 files changed

+180
-164
lines changed

pkg/front_end/lib/src/fragment/enum_element.dart

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,22 @@ class EnumElementFragment
2020
final Uri fileUri;
2121

2222
final ConstructorReferenceBuilder? constructorReferenceBuilder;
23-
Token? argumentsBeginToken;
23+
Token? _argumentsBeginToken;
2424

2525
SourcePropertyBuilder? _builder;
2626

2727
Field? _field;
28-
late DartType _type = new InferredType.fromEnumElementInitializer(this);
28+
29+
late DartType _type = new InferredType(
30+
libraryBuilder: builder.libraryBuilder,
31+
typeBuilder: type,
32+
inferType: inferType,
33+
computeType: _computeType,
34+
fileUri: fileUri,
35+
name: name,
36+
nameOffset: nameOffset,
37+
nameLength: name.length,
38+
token: argumentsBeginToken);
2939

3040
late final int elementIndex;
3141

@@ -38,7 +48,8 @@ class EnumElementFragment
3848
required this.nameOffset,
3949
required this.fileUri,
4050
required this.constructorReferenceBuilder,
41-
required this.argumentsBeginToken});
51+
required Token? argumentsBeginToken})
52+
: _argumentsBeginToken = argumentsBeginToken;
4253

4354
@override
4455
SourcePropertyBuilder get builder {
@@ -53,6 +64,29 @@ class EnumElementFragment
5364
type.registerInferredTypeListener(this);
5465
}
5566

67+
/// Returns the token for begin of the constructor arguments of this enum
68+
/// element, if any.
69+
///
70+
/// This can only be called once and will hand over the responsibility of
71+
/// the token to the caller.
72+
Token? get argumentsBeginToken {
73+
Token? token = _argumentsBeginToken;
74+
_argumentsBeginToken = null;
75+
return token;
76+
}
77+
78+
DartType _computeType(ClassHierarchyBase hierarchy, Token? token) {
79+
SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
80+
SourceEnumBuilder sourceEnumBuilder =
81+
builder.declarationBuilder as SourceEnumBuilder;
82+
_buildElement(
83+
sourceEnumBuilder,
84+
sourceEnumBuilder.selfType.build(libraryBuilder, TypeUse.enumSelfType),
85+
libraryBuilder.loader.coreTypes,
86+
token);
87+
return fieldType;
88+
}
89+
5690
@override
5791
bool get isEnumElement => true;
5892

@@ -125,8 +159,8 @@ class EnumElementFragment
125159
f(member: _field!, kind: BuiltMemberKind.Field);
126160
}
127161

128-
void buildElement(SourceEnumBuilder sourceEnumBuilder, DartType selfType,
129-
CoreTypes coreTypes) {
162+
void _buildElement(SourceEnumBuilder sourceEnumBuilder, DartType selfType,
163+
CoreTypes coreTypes, Token? token) {
130164
SourceLibraryBuilder libraryBuilder = sourceEnumBuilder.libraryBuilder;
131165
DartType inferredFieldType = selfType;
132166

@@ -174,8 +208,8 @@ class EnumElementFragment
174208
fileUri);
175209
bodyBuilder.constantContext = ConstantContext.inferred;
176210

177-
if (argumentsBeginToken != null) {
178-
arguments = bodyBuilder.parseArguments(argumentsBeginToken!);
211+
if (token != null) {
212+
arguments = bodyBuilder.parseArguments(token);
179213
// We pass `true` for [allowFurtherDelays] here because the members of
180214
// the enums are built before the inference, and the resolution of the
181215
// redirecting factories can't be completed at this moment and
@@ -185,7 +219,6 @@ class EnumElementFragment
185219

186220
arguments.positional.insertAll(0, enumSyntheticArguments);
187221
arguments.argumentsOriginalOrder?.insertAll(0, enumSyntheticArguments);
188-
argumentsBeginToken = null;
189222
} else {
190223
arguments = new ArgumentsImpl(enumSyntheticArguments);
191224
}

pkg/front_end/lib/src/fragment/field.dart

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,23 @@ class FieldFragment
6666
}
6767
}
6868

69+
/// Returns the token for the initializer of this field, if any.
70+
///
71+
/// This can only be called once and will hand over the responsibility of
72+
/// the token to the caller.
6973
Token? get initializerToken {
7074
Token? result = _initializerToken;
7175
// Ensure that we don't hold onto the token.
7276
_initializerToken = null;
7377
return result;
7478
}
7579

76-
// Coverage-ignore(suite): Not run.
80+
/// Returns the token for the initializer of this field, if any. This is the
81+
/// same as [initializerToken] but is used to signal that the initializer
82+
/// needs to be computed for outline expressions.
83+
///
84+
/// This can only be called once and will hand over the responsibility of
85+
/// the token to the caller.
7786
Token? get constInitializerToken {
7887
Token? result = _constInitializerToken;
7988
// Ensure that we don't hold onto the token.
@@ -173,13 +182,63 @@ class FieldFragment
173182
} else {
174183
// A field with no type and initializer or an instance field without
175184
// type and initializer need to have the type inferred.
176-
_encoding.type =
177-
new InferredType.fromFieldFragmentInitializer(this, token);
185+
_encoding.type = new InferredType(
186+
libraryBuilder: libraryBuilder,
187+
typeBuilder: type,
188+
inferType: inferType,
189+
computeType: _computeInferredType,
190+
fileUri: fileUri,
191+
name: name,
192+
nameOffset: nameOffset,
193+
nameLength: name.length,
194+
token: token);
178195
type.registerInferable(this);
179196
}
180197
}
181198
}
182199

200+
DartType _computeInferredType(
201+
ClassHierarchyBase classHierarchy, Token? token) {
202+
DartType? inferredType;
203+
SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
204+
DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
205+
if (token != null) {
206+
InterfaceType? enclosingClassThisType = declarationBuilder
207+
is SourceClassBuilder
208+
? libraryBuilder.loader.typeInferenceEngine.coreTypes
209+
.thisInterfaceType(
210+
declarationBuilder.cls, libraryBuilder.library.nonNullable)
211+
: null;
212+
TypeInferrer typeInferrer =
213+
libraryBuilder.loader.typeInferenceEngine.createTopLevelTypeInferrer(
214+
fileUri,
215+
enclosingClassThisType,
216+
libraryBuilder,
217+
builder
218+
.dataForTesting
219+
// Coverage-ignore(suite): Not run.
220+
?.inferenceData);
221+
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
222+
BodyBuilder bodyBuilder = libraryBuilder.loader.createBodyBuilderForField(
223+
libraryBuilder,
224+
bodyBuilderContext,
225+
declarationBuilder?.scope ?? libraryBuilder.scope,
226+
typeInferrer,
227+
fileUri);
228+
bodyBuilder.constantContext =
229+
modifiers.isConst ? ConstantContext.inferred : ConstantContext.none;
230+
bodyBuilder.inFieldInitializer = true;
231+
bodyBuilder.inLateFieldInitializer = modifiers.isLate;
232+
Expression initializer = bodyBuilder.parseFieldInitializer(token);
233+
234+
inferredType =
235+
typeInferrer.inferImplicitFieldType(bodyBuilder, initializer);
236+
} else {
237+
inferredType = const DynamicType();
238+
}
239+
return inferredType;
240+
}
241+
183242
@override
184243
bool get isEnumElement => false;
185244

@@ -240,13 +299,13 @@ class FieldFragment
240299
// For modular compilation we need to include initializers of all const
241300
// fields and all non-static final fields in classes with const constructors
242301
// into the outline.
302+
Token? token = constInitializerToken;
243303
if ((modifiers.isConst ||
244304
(isFinal &&
245305
isClassInstanceMember &&
246306
(declarationBuilder as SourceClassBuilder)
247307
.declaresConstConstructor)) &&
248-
_constInitializerToken != null) {
249-
Token initializerToken = _constInitializerToken!;
308+
token != null) {
250309
LookupScope scope = declarationBuilder?.scope ?? libraryBuilder.scope;
251310
BodyBuilder bodyBuilder = libraryBuilder.loader
252311
.createBodyBuilderForOutlineExpression(
@@ -255,18 +314,17 @@ class FieldFragment
255314
? ConstantContext.inferred
256315
: ConstantContext.required;
257316
Expression initializer = bodyBuilder.typeInferrer
258-
.inferFieldInitializer(bodyBuilder, fieldType,
259-
bodyBuilder.parseFieldInitializer(initializerToken))
317+
.inferFieldInitializer(
318+
bodyBuilder, fieldType, bodyBuilder.parseFieldInitializer(token))
260319
.expression;
261320
buildBody(classHierarchy.coreTypes, initializer);
262321
bodyBuilder.performBacklogComputations();
263322
if (computeSharedExpressionForTesting) {
264323
// Coverage-ignore-block(suite): Not run.
265324
_initializerExpression = parseFieldInitializer(libraryBuilder.loader,
266-
initializerToken, libraryBuilder.importUri, fileUri, scope);
325+
token, libraryBuilder.importUri, fileUri, scope);
267326
}
268327
}
269-
_constInitializerToken = null;
270328
}
271329

272330
@override

pkg/front_end/lib/src/fragment/fragment.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import '../source/source_type_alias_builder.dart';
5858
import '../source/type_parameter_scope_builder.dart';
5959
import '../type_inference/inference_results.dart';
6060
import '../type_inference/type_inference_engine.dart';
61+
import '../type_inference/type_inferrer.dart';
6162
import '../type_inference/type_schema.dart';
6263

6364
part 'class.dart';

0 commit comments

Comments
 (0)