Skip to content

Commit cbfd802

Browse files
scheglovCommit Queue
authored andcommitted
DeCo. Infer the type of declaring formal parameter and field from the default value.
Bug: #61701 Change-Id: Ibd2e468b409a2133b4ebea38da0f94ffdd7bef82 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/460200 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent b1e465a commit cbfd802

File tree

4 files changed

+347
-23
lines changed

4 files changed

+347
-23
lines changed

pkg/analyzer/lib/src/dart/element/element.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,12 +2802,6 @@ class FieldElementImpl extends PropertyInducingElementImpl
28022802
return super.setter;
28032803
}
28042804

2805-
@override
2806-
set type(TypeImpl value) {
2807-
super.type = value;
2808-
declaringFormalParameter?.type = value;
2809-
}
2810-
28112805
@override
28122806
List<FieldFragmentImpl> get _fragments {
28132807
return [

pkg/analyzer/lib/src/summary2/top_level_inference.dart

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analyzer/dart/element/scope.dart';
56
import 'package:analyzer/src/dart/analysis/analysis_options.dart';
67
import 'package:analyzer/src/dart/ast/ast.dart';
78
import 'package:analyzer/src/dart/ast/extensions.dart';
@@ -153,9 +154,22 @@ class _InitializerInference {
153154
}
154155

155156
void _addVariableNode(PropertyInducingElementImpl element) {
156-
if (element.isSynthetic &&
157-
!(element is FieldElementImpl && element.isSyntheticEnumField)) {
158-
return;
157+
if (element.isSynthetic) {
158+
var shouldInfer = false;
159+
if (element is FieldElementImpl) {
160+
// For enums `values` is purely synthetic.
161+
if (element.isEnumValues) {
162+
shouldInfer = true;
163+
}
164+
// For declaring formal parameters the field is synthetic.
165+
// But we want to infer the type from the default value.
166+
if (element.declaringFormalParameter != null) {
167+
shouldInfer = true;
168+
}
169+
}
170+
if (!shouldInfer) {
171+
return;
172+
}
159173
}
160174

161175
if (!element.hasImplicitType) return;
@@ -195,17 +209,33 @@ class _PropertyInducingElementTypeInference
195209

196210
@override
197211
TypeImpl perform() {
198-
PropertyInducingFragmentImpl? initializerFragment;
199-
VariableDeclarationImpl? variableDeclaration;
212+
LibraryFragmentImpl? initializerLibraryFragment;
213+
Scope? scope;
214+
ExpressionImpl Function()? getInitializer;
200215
for (var fragment in _element.fragments) {
201-
var node = _linker.elementNodes[fragment] as VariableDeclarationImpl;
202-
if (node.initializer != null) {
203-
initializerFragment = fragment;
204-
variableDeclaration = node;
216+
var node = _linker.elementNodes[fragment];
217+
switch (node) {
218+
case VariableDeclarationImpl():
219+
if (node.initializer != null) {
220+
initializerLibraryFragment = fragment.libraryFragment;
221+
scope = LinkingNodeContext.get(node).scope;
222+
getInitializer = () => node.initializer!;
223+
}
224+
case DefaultFormalParameterImpl():
225+
if (node.defaultValue != null) {
226+
initializerLibraryFragment = fragment.libraryFragment;
227+
scope = LinkingNodeContext.get(node).scope;
228+
getInitializer = () => node.defaultValue!;
229+
} else {
230+
_status = _InferenceStatus.inferred;
231+
return _element.library.typeSystem.objectQuestion;
232+
}
205233
}
206234
}
207235

208-
if (initializerFragment == null || variableDeclaration == null) {
236+
if (initializerLibraryFragment == null ||
237+
scope == null ||
238+
getInitializer == null) {
209239
_status = _InferenceStatus.inferred;
210240
return DynamicTypeImpl.instance;
211241
}
@@ -246,17 +276,15 @@ class _PropertyInducingElementTypeInference
246276
var enclosingInterfaceElement = enclosingElement
247277
.ifTypeOrNull<InterfaceElementImpl>();
248278

249-
var scope = LinkingNodeContext.get(variableDeclaration).scope;
250-
251279
var analysisOptions = _libraryBuilder.kind.file.analysisOptions;
252280
var astResolver = AstResolver(
253281
_linker,
254-
initializerFragment.libraryFragment,
282+
initializerLibraryFragment,
255283
scope,
256284
analysisOptions,
257285
enclosingClassElement: enclosingInterfaceElement,
258286
);
259-
astResolver.resolveExpression(() => variableDeclaration!.initializer!);
287+
astResolver.resolveExpression(getInitializer);
260288

261289
// Pop self from the stack.
262290
var self = _inferring.removeLast();
@@ -270,12 +298,19 @@ class _PropertyInducingElementTypeInference
270298
_status = _InferenceStatus.inferred;
271299
}
272300

273-
var initializerType = variableDeclaration.initializer!.typeOrThrow;
301+
var initializerType = getInitializer().typeOrThrow;
274302
return _refineType(initializerType);
275303
}
276304

277305
TypeImpl _refineType(TypeImpl type) {
278306
if (type.isDartCoreNull) {
307+
// When `T` is `Null`, `p` has declared type `Object?`.
308+
if (_element case FieldElementImpl field) {
309+
if (field.declaringFormalParameter != null) {
310+
return _element.library.typeSystem.objectQuestion;
311+
}
312+
}
313+
// Logic for older language versions.
279314
return DynamicTypeImpl.instance;
280315
}
281316

pkg/analyzer/lib/src/summary2/types_builder.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,22 @@ class TypesBuilder {
397397

398398
void _simpleFormalParameter(SimpleFormalParameterImpl node) {
399399
var fragment = node.declaredFragment!;
400-
if (fragment.previousFragment == null) {
401-
fragment.element.type = node.type?.type ?? _dynamicType;
400+
if (fragment.previousFragment != null) {
401+
return;
402+
}
403+
404+
var element = fragment.element;
405+
406+
var typeAnnotation = node.type;
407+
if (typeAnnotation == null) {
408+
// For a declaring formal parameter the type will be inferred from
409+
// the field type via instance inference, or from the default value.
410+
if (element is FieldFormalParameterElementImpl && element.isDeclaring) {
411+
return;
412+
}
413+
element.type = _dynamicType;
414+
} else {
415+
element.type = typeAnnotation.typeOrThrow;
402416
}
403417
}
404418

0 commit comments

Comments
 (0)