@@ -268,6 +268,7 @@ class ResolutionWorldBuilder extends WorldBuilder
268268 bool _closed = false ;
269269 KClosedWorld ? _closedWorldCache;
270270 final Set <MemberEntity > _liveInstanceMembers = {};
271+ final Set <MemberEntity > _liveAbstractInstanceMembers = {};
271272
272273 final Set <ConstantValue > _constantValues = {};
273274
@@ -451,9 +452,10 @@ class ResolutionWorldBuilder extends WorldBuilder
451452 EnumSet <MemberUse > action (MemberUsage usage),
452453 bool shouldBeRemoved (MemberUsage usage)) {
453454 _processSet (memberMap, methodName, (MemberUsage usage) {
454- if (selector.appliesUnnamed (usage.entity) &&
455- _selectorConstraintsStrategy.appliedUnnamed (
456- dynamicUse, usage.entity, this )) {
455+ if (usage.entity.isAbstract ||
456+ selector.appliesUnnamed (usage.entity) &&
457+ (_selectorConstraintsStrategy.appliedUnnamed (
458+ dynamicUse, usage.entity, this ))) {
457459 memberUsed (usage.entity, action (usage));
458460 return shouldBeRemoved (usage);
459461 }
@@ -680,11 +682,23 @@ class ResolutionWorldBuilder extends WorldBuilder
680682 {bool checkEnqueuerConsistency = false }) {
681683 _elementEnvironment.forEachClassMember (cls,
682684 (ClassEntity cls, MemberEntity member) {
683- _processInstantiatedClassMember (cls, member, memberUsed,
685+ _processMemberInUsedClass (cls, member, memberUsed,
684686 checkEnqueuerConsistency: checkEnqueuerConsistency);
685687 });
686688 }
687689
690+ @override
691+ void processAbstractClassMembers (
692+ ClassEntity cls, MemberUsedCallback memberUsed) {
693+ _elementEnvironment.forEachLocalClassMember (cls, (MemberEntity member) {
694+ if (member.isAbstract) {
695+ // Check for potential usages of abstract members (i.e. of their
696+ // overrides) and save them if they are used.
697+ _processMemberInUsedClass (cls, member, memberUsed);
698+ }
699+ });
700+ }
701+
688702 /// Call [updateUsage] on all [MemberUsage] s in the set in [map] for
689703 /// [memberName] . If [updateUsage] returns `true` the usage is removed from
690704 /// the set.
@@ -785,7 +799,13 @@ class ResolutionWorldBuilder extends WorldBuilder
785799 return usage;
786800 }
787801
788- void _processInstantiatedClassMember (
802+ /// Determines whether [member] is potentially used and calls the [memberUsed]
803+ /// callback on it if it is.
804+ ///
805+ /// [member] can be concrete or abstract and in either case potential usage
806+ /// is determined by comparing the signature of [member] to the selector
807+ /// structure (including arguments) at call sites.
808+ void _processMemberInUsedClass (
789809 ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed,
790810 {bool checkEnqueuerConsistency = false }) {
791811 if (! member.isInstanceMember) return ;
@@ -851,8 +871,12 @@ class ResolutionWorldBuilder extends WorldBuilder
851871
852872 @override
853873 void registerUsedElement (MemberEntity element) {
854- if (element.isInstanceMember && ! element.isAbstract) {
855- _liveInstanceMembers.add (element);
874+ if (element.isInstanceMember) {
875+ if (element.isAbstract) {
876+ _liveAbstractInstanceMembers.add (element);
877+ } else {
878+ _liveInstanceMembers.add (element);
879+ }
856880 }
857881 }
858882
@@ -997,6 +1021,7 @@ class ResolutionWorldBuilder extends WorldBuilder
9971021 implementedClasses: _implementedClasses,
9981022 liveNativeClasses: _nativeResolutionEnqueuer.liveNativeClasses,
9991023 liveInstanceMembers: _liveInstanceMembers,
1024+ liveAbstractInstanceMembers: _liveAbstractInstanceMembers,
10001025 assignedInstanceMembers: computeAssignedInstanceMembers (),
10011026 liveMemberUsage: liveMemberUsage,
10021027 mixinUses: _classHierarchyBuilder.mixinUses,
0 commit comments