@@ -240,12 +240,7 @@ abstract class ItemNode extends Locatable {
240240 )
241241 or
242242 // 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 )
249244 or
250245 // trait items with default implementations made available in an implementation
251246 exists ( ImplItemNodeImpl impl , ItemNode trait |
@@ -1422,10 +1417,33 @@ private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKi
14221417pragma [ nomagic]
14231418private predicate isUnqualifiedSelfPath ( RelevantPath path ) { path .isUnqualified ( "Self" ) }
14241419
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+ }
14291447}
14301448
14311449pragma [ nomagic]
@@ -1453,14 +1471,6 @@ private ItemNode resolvePathCandQualifier(RelevantPath qualifier, RelevantPath p
14531471 name = path .getText ( )
14541472}
14551473
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-
14641474/**
14651475 * Gets the item that `path` resolves to in `ns` when `qualifier` is the
14661476 * qualifier of `path` and `qualifier` resolves to `q`, if any.
@@ -1539,6 +1549,19 @@ private ItemNode resolvePathCand(RelevantPath path) {
15391549 )
15401550}
15411551
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+
15421565/** Gets the item that `path` resolves to, if any. */
15431566cached
15441567ItemNode resolvePath ( RelevantPath path ) {
@@ -1547,9 +1570,9 @@ ItemNode resolvePath(RelevantPath path) {
15471570 (
15481571 // When the result is an associated item of a trait implementation the
15491572 // implemented trait must be visible.
1550- traitIsVisible ( path , assocItemImplementsTrait ( pragma [ only_bind_out ] ( result ) ) )
1573+ TraitIsVisible < pathTraitUsed / 2 > :: traitIsVisible ( path , getResolvePathTraitUsed ( path , result ) )
15511574 or
1552- not exists ( ImplItemNode impl | impl . getAnAssocItem ( ) = result and impl . ( Impl ) . hasTrait ( ) )
1575+ not exists ( getResolvePathTraitUsed ( path , result ) )
15531576 )
15541577 or
15551578 // if `path` is the qualifier of a resolvable `parent`, then we should
@@ -1663,6 +1686,18 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
16631686 )
16641687}
16651688
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+
16661701pragma [ nomagic]
16671702private predicate preludeItem ( string name , ItemNode i ) {
16681703 exists ( Crate stdOrCore , ModuleLikeNode mod , ModuleItemNode prelude , ModuleItemNode rust |
0 commit comments