@@ -240,12 +240,7 @@ abstract class ItemNode extends Locatable {
240
240
)
241
241
or
242
242
// items made available by an implementation where `this` is the implementing type
243
- exists ( ItemNode node |
244
- this = node .( ImplItemNodeImpl ) .resolveSelfTyCand ( ) and
245
- result = node .getASuccessor ( name , kind ) and
246
- kind .isExternalOrBoth ( ) and
247
- result instanceof AssocItemNode
248
- )
243
+ typeImplEdge ( this , _, name , kind , result )
249
244
or
250
245
// trait items with default implementations made available in an implementation
251
246
exists ( ImplItemNodeImpl impl , ItemNode trait |
@@ -1422,10 +1417,33 @@ private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKi
1422
1417
pragma [ nomagic]
1423
1418
private predicate isUnqualifiedSelfPath ( RelevantPath path ) { path .isUnqualified ( "Self" ) }
1424
1419
1425
- /** Holds if the trait `trait` is visible at the element `element`. */
1426
- bindingset [ element, trait]
1427
- predicate traitIsVisible ( Element element , TraitItemNode trait ) {
1428
- exists ( ItemNode encl | encl .getADescendant * ( ) = element and trait = encl .getASuccessor ( _, _) )
1420
+ /** Provides the input to `TraitIsVisible`. */
1421
+ signature predicate relevantTraitVisibleSig ( Element element , Trait trait ) ;
1422
+
1423
+ /**
1424
+ * Provides the `traitIsVisible` predicate for determining if a trait is visible
1425
+ * at a given element.
1426
+ */
1427
+ module TraitIsVisible< relevantTraitVisibleSig / 2 relevantTraitVisible> {
1428
+ /** Holds if the trait might be looked up in `encl`. */
1429
+ private predicate traitLookup ( ItemNode encl , Element element , Trait trait ) {
1430
+ // lookup in immediately enclosing item
1431
+ relevantTraitVisible ( element , trait ) and
1432
+ encl .getADescendant ( ) = element
1433
+ or
1434
+ // lookup in an outer scope, but only if the trait is not declared in inner scope
1435
+ exists ( ItemNode mid |
1436
+ traitLookup ( mid , element , trait ) and
1437
+ not trait = mid .getASuccessor ( _, _) and
1438
+ encl = getOuterScope ( mid )
1439
+ )
1440
+ }
1441
+
1442
+ /** Holds if the trait `trait` is visible at `element`. */
1443
+ pragma [ nomagic]
1444
+ predicate traitIsVisible ( Element element , Trait trait ) {
1445
+ exists ( ItemNode encl | traitLookup ( encl , element , trait ) and trait = encl .getASuccessor ( _, _) )
1446
+ }
1429
1447
}
1430
1448
1431
1449
pragma [ nomagic]
@@ -1453,14 +1471,6 @@ private ItemNode resolvePathCandQualifier(RelevantPath qualifier, RelevantPath p
1453
1471
name = path .getText ( )
1454
1472
}
1455
1473
1456
- pragma [ nomagic]
1457
- private TraitItemNode assocItemImplementsTrait ( AssocItemNode assoc ) {
1458
- exists ( ImplItemNodeImpl impl |
1459
- impl .getAnAssocItem ( ) = assoc and
1460
- result = impl .resolveTraitTyCand ( )
1461
- )
1462
- }
1463
-
1464
1474
/**
1465
1475
* Gets the item that `path` resolves to in `ns` when `qualifier` is the
1466
1476
* qualifier of `path` and `qualifier` resolves to `q`, if any.
@@ -1539,6 +1549,19 @@ private ItemNode resolvePathCand(RelevantPath path) {
1539
1549
)
1540
1550
}
1541
1551
1552
+ /** Get a trait that should be visible when `path` resolves to `node`, if any. */
1553
+ private Trait getResolvePathTraitUsed ( RelevantPath path , AssocItemNode node ) {
1554
+ exists ( TypeItemNode type , ImplItemNodeImpl impl |
1555
+ node = resolvePathCandQualified ( _, type , path , _) and
1556
+ typeImplEdge ( type , impl , _, _, node ) and
1557
+ result = impl .resolveTraitTyCand ( )
1558
+ )
1559
+ }
1560
+
1561
+ private predicate pathTraitUsed ( Element path , Trait trait ) {
1562
+ trait = getResolvePathTraitUsed ( path , _)
1563
+ }
1564
+
1542
1565
/** Gets the item that `path` resolves to, if any. */
1543
1566
cached
1544
1567
ItemNode resolvePath ( RelevantPath path ) {
@@ -1547,9 +1570,9 @@ ItemNode resolvePath(RelevantPath path) {
1547
1570
(
1548
1571
// When the result is an associated item of a trait implementation the
1549
1572
// implemented trait must be visible.
1550
- traitIsVisible ( path , assocItemImplementsTrait ( pragma [ only_bind_out ] ( result ) ) )
1573
+ TraitIsVisible < pathTraitUsed / 2 > :: traitIsVisible ( path , getResolvePathTraitUsed ( path , result ) )
1551
1574
or
1552
- not exists ( ImplItemNode impl | impl . getAnAssocItem ( ) = result and impl . ( Impl ) . hasTrait ( ) )
1575
+ not exists ( getResolvePathTraitUsed ( path , result ) )
1553
1576
)
1554
1577
or
1555
1578
// if `path` is the qualifier of a resolvable `parent`, then we should
@@ -1663,6 +1686,18 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
1663
1686
)
1664
1687
}
1665
1688
1689
+ /**
1690
+ * Holds if `typeItem` is the implementing type of `impl` and the implementation
1691
+ * makes `assoc` available as `name` at `kind`.
1692
+ */
1693
+ private predicate typeImplEdge (
1694
+ TypeItemNode typeItem , ImplItemNodeImpl impl , string name , SuccessorKind kind , AssocItemNode assoc
1695
+ ) {
1696
+ typeItem = impl .resolveSelfTyCand ( ) and
1697
+ assoc = impl .getASuccessor ( name , kind ) and
1698
+ kind .isExternalOrBoth ( )
1699
+ }
1700
+
1666
1701
pragma [ nomagic]
1667
1702
private predicate preludeItem ( string name , ItemNode i ) {
1668
1703
exists ( Crate stdOrCore , ModuleLikeNode mod , ModuleItemNode prelude , ModuleItemNode rust |
0 commit comments