Skip to content

Commit 9e5e16c

Browse files
scheglovCommit Queue
authored andcommitted
Elements. Perform mixin inference on InterfaceElementImpl, not on
Previously, mixin inference data was collected for each interface fragment individually, including augmentations. This data was then combined, which required managing separate information for the declaration and each augmentation, as well as handling substitutions between them. This change refactors the mixin inference process to be associated with the whole `InterfaceElementImpl` rather than individual fragments. The `TypesBuilder` now collects all fragments that have a `with` clause for a given element. A single `_MixinsInference` instance then iterates through these fragments and performs inference for each one within the context of the whole element. This is orchestrated by the new `_addFragmentWithClause` method, which gathers all relevant fragments (both declarations and augmentations) under their parent element. This new approach simplifies the logic significantly: - It removes the need for the previous complex logic that handled augmentations separately in `_inferDeclaration`. Augmentations are now treated uniformly with the base declaration. - It allows for the removal of redundant calls to the old `_updatedAugmented` function for declarations like `extension` and `mixin` that do not support mixins themselves. This refactoring makes the mixin inference logic cleaner and easier to follow, especially with the presence of augmentations, while preserving the existing functionality. The functionality is the same. Change-Id: Iaef78af37e76eeb82e2600112fcc2b483cce5bad Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/442284 Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 980baae commit 9e5e16c

File tree

3 files changed

+51
-97
lines changed

3 files changed

+51
-97
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4839,6 +4839,10 @@ abstract class InterfaceElementImpl extends InstanceElementImpl
48394839

48404840
List<ConstructorElementImpl> _constructors = _Sentinel.constructorElement;
48414841

4842+
/// This callback is set during mixins inference to handle reentrant calls.
4843+
List<InterfaceTypeImpl>? Function(InterfaceElementImpl)?
4844+
mixinInferenceCallback;
4845+
48424846
/// A flag indicating whether the types associated with the instance members
48434847
/// of this class have been inferred.
48444848
bool hasBeenInferred = false;
@@ -5202,10 +5206,6 @@ abstract class InterfaceFragmentImpl extends InstanceFragmentImpl
52025206
/// class.
52035207
List<InterfaceTypeImpl> _interfaces = const [];
52045208

5205-
/// This callback is set during mixins inference to handle reentrant calls.
5206-
List<InterfaceTypeImpl>? Function(InterfaceFragmentImpl)?
5207-
mixinInferenceCallback;
5208-
52095209
InterfaceTypeImpl? _supertype;
52105210

52115211
List<ConstructorFragmentImpl> _constructors = _Sentinel.constructorFragment;
@@ -5282,8 +5282,8 @@ abstract class InterfaceFragmentImpl extends InstanceFragmentImpl
52825282

52835283
@override
52845284
List<InterfaceTypeImpl> get mixins {
5285-
if (mixinInferenceCallback != null) {
5286-
var mixins = mixinInferenceCallback!(this);
5285+
if (element.mixinInferenceCallback case var mixinInferenceCallback?) {
5286+
var mixins = mixinInferenceCallback(element);
52875287
if (mixins != null) {
52885288
return _mixins = mixins;
52895289
}

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

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ void detachElementsFromNodes(LibraryElementImpl element) {
2020
class _Visitor extends GeneralizingElementVisitor2<void> {
2121
@override
2222
void visitClassElement(covariant ClassElementImpl element) {
23-
for (var fragment in element.fragments) {
24-
fragment.mixinInferenceCallback = null;
25-
}
23+
element.mixinInferenceCallback = null;
2624
super.visitClassElement(element);
2725
}
2826

@@ -73,9 +71,7 @@ class _Visitor extends GeneralizingElementVisitor2<void> {
7371

7472
@override
7573
void visitEnumElement(covariant EnumElementImpl element) {
76-
for (var fragment in element.fragments) {
77-
fragment.mixinInferenceCallback = null;
78-
}
74+
element.mixinInferenceCallback = null;
7975
super.visitEnumElement(element);
8076
}
8177

@@ -87,9 +83,7 @@ class _Visitor extends GeneralizingElementVisitor2<void> {
8783

8884
@override
8985
void visitMixinElement(covariant MixinElementImpl element) {
90-
for (var fragment in element.fragments) {
91-
fragment.mixinInferenceCallback = null;
92-
}
86+
element.mixinInferenceCallback = null;
9387
super.visitMixinElement(element);
9488
}
9589

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

Lines changed: 42 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:analyzer/src/dart/ast/extensions.dart';
1010
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
1111
import 'package:analyzer/src/dart/element/element.dart';
1212
import 'package:analyzer/src/dart/element/type.dart';
13-
import 'package:analyzer/src/dart/element/type_algebra.dart';
1413
import 'package:analyzer/src/dart/element/type_system.dart';
1514
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
1615
import 'package:analyzer/src/summary2/default_types_builder.dart';
@@ -71,7 +70,7 @@ class NodesToBuildType {
7170

7271
class TypesBuilder {
7372
final Linker _linker;
74-
final Map<InstanceFragmentImpl, _ToInferMixins> _toInferMixins = {};
73+
final Map<InstanceElementImpl, _ToInferMixins> _toInferMixins = {};
7574

7675
TypesBuilder(this._linker);
7776

@@ -97,6 +96,17 @@ class TypesBuilder {
9796
_MixinsInference(_toInferMixins).perform();
9897
}
9998

99+
void _addFragmentWithClause(
100+
InterfaceFragmentImpl fragment,
101+
WithClauseImpl? withClause,
102+
) {
103+
if (withClause != null) {
104+
var element = fragment.element;
105+
var inferrer = _toInferMixins[element] ??= _ToInferMixins(element);
106+
inferrer.fragments.add(_ToInferFragmentMixins(fragment, withClause));
107+
}
108+
}
109+
100110
FunctionTypeImpl _buildFunctionType(
101111
TypeParameterListImpl? typeParameterList,
102112
TypeAnnotationImpl? returnTypeNode,
@@ -132,7 +142,7 @@ class TypesBuilder {
132142
node.implementsClause?.interfaces,
133143
);
134144

135-
_updatedAugmented(element, withClause: node.withClause);
145+
_addFragmentWithClause(element, node.withClause);
136146
}
137147

138148
void _classTypeAlias(ClassTypeAliasImpl node) {
@@ -149,9 +159,7 @@ class TypesBuilder {
149159
node.implementsClause?.interfaces,
150160
);
151161

152-
_updatedAugmented(element, withClause: node.withClause);
153-
154-
_toInferMixins[element] = _ToInferMixins(element, node.withClause);
162+
_addFragmentWithClause(element, node.withClause);
155163
}
156164

157165
void _declaration(AstNode node) {
@@ -201,7 +209,7 @@ class TypesBuilder {
201209
node.implementsClause?.interfaces,
202210
);
203211

204-
_updatedAugmented(fragment, withClause: node.withClause);
212+
_addFragmentWithClause(fragment, node.withClause);
205213
}
206214

207215
void _extensionDeclaration(ExtensionDeclarationImpl node) {
@@ -226,8 +234,6 @@ class TypesBuilder {
226234
if (interfaces != null) {
227235
fragment.interfaces = interfaces;
228236
}
229-
230-
_updatedAugmented(fragment);
231237
}
232238

233239
void _fieldFormalParameter(FieldFormalParameterImpl node) {
@@ -337,8 +343,6 @@ class TypesBuilder {
337343
fragment.interfaces = _toInterfaceTypeList(
338344
node.implementsClause?.interfaces,
339345
);
340-
341-
_updatedAugmented(fragment);
342346
}
343347

344348
NullabilitySuffix _nullability(AstNode node, bool hasQuestion) {
@@ -396,22 +400,6 @@ class TypesBuilder {
396400
return node.typeParameters.map((p) => p.declaredFragment!).toFixedList();
397401
}
398402

399-
// TODO(scheglov): remove it, mostly.
400-
void _updatedAugmented(
401-
InstanceFragmentImpl fragment, {
402-
WithClause? withClause,
403-
}) {
404-
if (fragment is InterfaceFragmentImpl) {
405-
_toInferMixins[fragment] = _ToInferMixins(fragment, withClause);
406-
}
407-
408-
// TODO(scheglov): restore?
409-
// var element = fragment.element;
410-
// if (fragment is MixinFragmentImpl && element is MixinElementImpl2) {
411-
// element.superclassConstraints.addAll(fragment.superclassConstraints);
412-
// }
413-
}
414-
415403
void _variableDeclarationList(VariableDeclarationListImpl node) {
416404
var type = node.type?.type;
417405
if (type != null) {
@@ -437,7 +425,7 @@ class TypesBuilder {
437425

438426
/// Performs mixins inference in a [ClassDeclaration].
439427
class _MixinInference {
440-
final InterfaceFragmentImpl element;
428+
final InterfaceElementImpl element;
441429
final TypeSystemImpl typeSystem;
442430
final FeatureSet featureSet;
443431
final InterfaceType classType;
@@ -449,8 +437,8 @@ class _MixinInference {
449437
this.element,
450438
this.featureSet, {
451439
required this.typeSystemOperations,
452-
}) : typeSystem = element.element.library.typeSystem,
453-
classType = element.element.thisType {
440+
}) : typeSystem = element.library.typeSystem,
441+
classType = element.thisType {
454442
interfacesMerger = InterfacesMerger(typeSystem);
455443
interfacesMerger.addWithSupertypes(element.supertype);
456444
}
@@ -461,10 +449,10 @@ class _MixinInference {
461449
}
462450
}
463451

464-
List<InterfaceTypeImpl> perform(WithClause withClause) {
452+
List<InterfaceTypeImpl> perform(WithClauseImpl withClause) {
465453
var result = <InterfaceTypeImpl>[];
466454
for (var mixinNode in withClause.mixinTypes) {
467-
var mixinType = _inferSingle(mixinNode as NamedTypeImpl);
455+
var mixinType = _inferSingle(mixinNode);
468456
if (mixinType != null && _isInterfaceTypeInterface(mixinType)) {
469457
result.add(mixinType);
470458
interfacesMerger.addWithSupertypes(mixinType);
@@ -600,7 +588,7 @@ class _MixinInference {
600588

601589
/// Performs mixin inference for all declarations.
602590
class _MixinsInference {
603-
final Map<InstanceFragmentImpl, _ToInferMixins> _declarations;
591+
final Map<InstanceElementImpl, _ToInferMixins> _declarations;
604592

605593
_MixinsInference(this._declarations);
606594

@@ -621,15 +609,15 @@ class _MixinsInference {
621609
/// we are inferring the [element] now, i.e. there is a loop.
622610
///
623611
/// This is an error. So, we return the empty list, and break the loop.
624-
List<InterfaceTypeImpl> _callbackWhenLoop(InterfaceFragmentImpl element) {
612+
List<InterfaceTypeImpl> _callbackWhenLoop(InterfaceElementImpl element) {
625613
element.mixinInferenceCallback = null;
626614
return <InterfaceTypeImpl>[];
627615
}
628616

629617
/// This method is invoked when mixins are asked from the [element], and
630618
/// we are not inferring the [element] now, i.e. there is no loop.
631619
List<InterfaceTypeImpl>? _callbackWhenRecursion(
632-
InterfaceFragmentImpl element,
620+
InterfaceElementImpl element,
633621
) {
634622
var declaration = _declarations[element];
635623
if (declaration != null) {
@@ -643,8 +631,7 @@ class _MixinsInference {
643631
var element = declaration.element;
644632
element.mixinInferenceCallback = _callbackWhenLoop;
645633

646-
var library = element.element.library;
647-
var declarationMixins = <InterfaceTypeImpl>[];
634+
var library = element.library;
648635

649636
try {
650637
// Casts aren't relevant for mixin inference.
@@ -653,31 +640,14 @@ class _MixinsInference {
653640
strictCasts: false,
654641
);
655642

656-
if (declaration.withClause case var withClause?) {
657-
var inference = _MixinInference(
658-
element,
659-
library.featureSet,
660-
typeSystemOperations: typeSystemOperations,
661-
);
662-
var inferred = inference.perform(withClause);
663-
element.mixins = inferred;
664-
declarationMixins.addAll(inferred);
665-
}
666-
667-
for (var augmentation in declaration.augmentations) {
668-
var inference = _MixinInference(
669-
element,
670-
library.featureSet,
671-
typeSystemOperations: typeSystemOperations,
672-
);
673-
inference.addTypes(
674-
augmentation.fromDeclaration.mapInterfaceTypes(declarationMixins),
675-
);
676-
var inferred = inference.perform(augmentation.withClause);
677-
augmentation.element.mixins = inferred;
678-
declarationMixins.addAll(
679-
augmentation.toDeclaration.mapInterfaceTypes(inferred),
680-
);
643+
var inference = _MixinInference(
644+
element,
645+
library.featureSet,
646+
typeSystemOperations: typeSystemOperations,
647+
);
648+
for (var fragment in declaration.fragments) {
649+
var inferred = inference.perform(fragment.withClause);
650+
fragment.fragment.mixins = inferred;
681651
}
682652
} finally {
683653
element.mixinInferenceCallback = null;
@@ -690,33 +660,23 @@ class _MixinsInference {
690660
/// hierarchies for all classes being linked, indiscriminately.
691661
void _resetHierarchies() {
692662
for (var declaration in _declarations.values) {
693-
var element = declaration.element.element;
663+
var element = declaration.element;
694664
element.library.session.classHierarchy.remove(element);
695665
}
696666
}
697667
}
698668

699-
/// The declaration of a class that can have mixins.
700-
class _ToInferMixins {
701-
final InterfaceFragmentImpl element;
702-
final WithClause? withClause;
703-
final List<_ToInferMixinsAugmentation> augmentations = [];
669+
class _ToInferFragmentMixins {
670+
final InterfaceFragmentImpl fragment;
671+
final WithClauseImpl withClause;
704672

705-
_ToInferMixins(this.element, this.withClause);
673+
_ToInferFragmentMixins(this.fragment, this.withClause);
706674
}
707675

708-
class _ToInferMixinsAugmentation {
709-
final InterfaceFragmentImpl element;
710-
final WithClause withClause;
711-
final MapSubstitution toDeclaration;
712-
final MapSubstitution fromDeclaration;
676+
/// The declaration of a class that can have mixins.
677+
class _ToInferMixins {
678+
final InterfaceElementImpl element;
679+
final List<_ToInferFragmentMixins> fragments = [];
713680

714-
_ToInferMixinsAugmentation({
715-
required this.element,
716-
required this.withClause,
717-
required this.toDeclaration,
718-
required this.fromDeclaration,
719-
}) {
720-
assert(element.isAugmentation);
721-
}
681+
_ToInferMixins(this.element);
722682
}

0 commit comments

Comments
 (0)