Skip to content

Commit 13cc09a

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Make ancestry helpers ID-tracked; tie members to container
Reclassify `thisOrAncestorMatching()` and `thisOrAncestorOfType()` from `@trackedDirectlyOpaque` to `@trackedIncludedInId` and remove opaque `recordOpaqueApiUse` calls. Using these helpers now contributes to the consumer’s dependency graph through element IDs rather than an opaque side channel. Augment manifest matching so members explicitly depend on their enclosing container: - Pass the enclosing `instanceElement`/`interfaceElement` into member matchers (fields, getters, setters, methods) and constructors. - Add the container element to the `MatchContext` when a member matches. This fixes a bug where a member’s ID could stay stable when only the container changed (e.g., superclass/mixin changes), leading to stale reuse. When the container’s ID changes, affected members now get new IDs, ensuring correct invalidation for ancestry-sensitive queries. Trade-off: this increases invalidation fan-out—more member IDs will change when a container changes—which can reduce cache reuse and increase rebuild work. We accept this for correctness; if needed we can mitigate by making member–container dependencies more selective (e.g., depending only on container “interface” stamps that affect member signatures). Change-Id: I01259590dc30d9735f0f436a59130d07d0bd9681 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/450101 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 8678711 commit 13cc09a

File tree

3 files changed

+992
-47
lines changed

3 files changed

+992
-47
lines changed

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

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,12 +1935,8 @@ abstract class ElementImpl implements Element {
19351935
}
19361936

19371937
@override
1938-
@trackedDirectlyOpaque
1938+
@trackedIncludedInId
19391939
Element? thisOrAncestorMatching(bool Function(Element p1) predicate) {
1940-
globalResultRequirements?.recordOpaqueApiUse(
1941-
this,
1942-
'thisOrAncestorMatching',
1943-
);
19441940
Element? element = this;
19451941
while (element != null && !predicate(element)) {
19461942
element = element.enclosingElement;
@@ -1956,9 +1952,8 @@ abstract class ElementImpl implements Element {
19561952
}
19571953

19581954
@override
1959-
@trackedDirectlyOpaque
1955+
@trackedIncludedInId
19601956
E? thisOrAncestorOfType<E extends Element>() {
1961-
globalResultRequirements?.recordOpaqueApiUse(this, 'thisOrAncestorOfType');
19621957
Element element = this;
19631958
while (element is! E) {
19641959
var ancestor = element.enclosingElement;
@@ -4603,12 +4598,8 @@ abstract class InstanceElementImpl extends ElementImpl
46034598
}
46044599

46054600
@override
4606-
@trackedDirectlyOpaque
4601+
@trackedIncludedInId
46074602
Element? thisOrAncestorMatching(bool Function(Element) predicate) {
4608-
globalResultRequirements?.recordOpaqueApiUse(
4609-
this,
4610-
'thisOrAncestorMatching',
4611-
);
46124603
if (predicate(this)) {
46134604
return this;
46144605
}
@@ -4623,9 +4614,8 @@ abstract class InstanceElementImpl extends ElementImpl
46234614
}
46244615

46254616
@override
4626-
@trackedDirectlyOpaque
4617+
@trackedIncludedInId
46274618
E? thisOrAncestorOfType<E extends Element>() {
4628-
globalResultRequirements?.recordOpaqueApiUse(this, 'thisOrAncestorOfType');
46294619
if (this case E result) {
46304620
return result;
46314621
}

pkg/analyzer/lib/src/fine/library_manifest.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,7 @@ class _LibraryMatch {
14321432
}) {
14331433
for (var field in element.fields) {
14341434
if (!_matchInstanceElementField(
1435+
instanceElement: element,
14351436
instanceItem: item,
14361437
instanceMatchContext: matchContext,
14371438
element: field,
@@ -1442,6 +1443,7 @@ class _LibraryMatch {
14421443

14431444
for (var method in element.methods) {
14441445
if (!_matchInstanceElementMethod(
1446+
instanceElement: element,
14451447
instanceItem: item,
14461448
instanceMatchContext: matchContext,
14471449
element: method,
@@ -1452,6 +1454,7 @@ class _LibraryMatch {
14521454

14531455
for (var getter in element.getters) {
14541456
if (!_matchInstanceElementGetter(
1457+
instanceElement: element,
14551458
instanceItem: item,
14561459
instanceMatchContext: matchContext,
14571460
element: getter,
@@ -1462,6 +1465,7 @@ class _LibraryMatch {
14621465

14631466
for (var setter in element.setters) {
14641467
if (!_matchInstanceElementSetter(
1468+
instanceElement: element,
14651469
instanceItem: item,
14661470
instanceMatchContext: matchContext,
14671471
element: setter,
@@ -1472,6 +1476,7 @@ class _LibraryMatch {
14721476
}
14731477

14741478
bool _matchInstanceElementField({
1479+
required InstanceElementImpl instanceElement,
14751480
required InstanceItem instanceItem,
14761481
required MatchContext instanceMatchContext,
14771482
required FieldElementImpl element,
@@ -1491,11 +1496,13 @@ class _LibraryMatch {
14911496
return false;
14921497
}
14931498

1499+
matchContext.elements.add(instanceElement);
14941500
_addMatchingElementItem(element, item, matchContext);
14951501
return true;
14961502
}
14971503

14981504
bool _matchInstanceElementGetter({
1505+
required InstanceElementImpl instanceElement,
14991506
required InstanceItem instanceItem,
15001507
required MatchContext instanceMatchContext,
15011508
required GetterElementImpl element,
@@ -1515,11 +1522,13 @@ class _LibraryMatch {
15151522
return false;
15161523
}
15171524

1525+
matchContext.elements.add(instanceElement);
15181526
_addMatchingElementItem(element, item, matchContext);
15191527
return true;
15201528
}
15211529

15221530
bool _matchInstanceElementMethod({
1531+
required InstanceElementImpl instanceElement,
15231532
required InstanceItem instanceItem,
15241533
required MatchContext instanceMatchContext,
15251534
required MethodElementImpl element,
@@ -1539,11 +1548,13 @@ class _LibraryMatch {
15391548
return false;
15401549
}
15411550

1551+
matchContext.elements.add(instanceElement);
15421552
_addMatchingElementItem(element, item, matchContext);
15431553
return true;
15441554
}
15451555

15461556
bool _matchInstanceElementSetter({
1557+
required InstanceElementImpl instanceElement,
15471558
required InstanceItem instanceItem,
15481559
required MatchContext instanceMatchContext,
15491560
required SetterElementImpl element,
@@ -1563,11 +1574,13 @@ class _LibraryMatch {
15631574
return false;
15641575
}
15651576

1577+
matchContext.elements.add(instanceElement);
15661578
_addMatchingElementItem(element, item, matchContext);
15671579
return true;
15681580
}
15691581

15701582
bool _matchInterfaceElementConstructor({
1583+
required InterfaceElementImpl interfaceElement,
15711584
required InterfaceItem interfaceItem,
15721585
required MatchContext interfaceMatchContext,
15731586
required ConstructorElementImpl element,
@@ -1587,6 +1600,7 @@ class _LibraryMatch {
15871600
return false;
15881601
}
15891602

1603+
matchContext.elements.add(interfaceElement);
15901604
_addMatchingElementItem(element, item, matchContext);
15911605
return true;
15921606
}
@@ -1598,6 +1612,7 @@ class _LibraryMatch {
15981612
}) {
15991613
for (var constructor in interfaceElement.constructors) {
16001614
if (!_matchInterfaceElementConstructor(
1615+
interfaceElement: interfaceElement,
16011616
interfaceItem: item,
16021617
interfaceMatchContext: matchContext,
16031618
element: constructor,

0 commit comments

Comments
 (0)