@@ -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]
@@ -1539,6 +1557,19 @@ private ItemNode resolvePathCand(RelevantPath path) {
15391557 )
15401558}
15411559
1560+ /** Get a trait that should be visible when `path` resolves to `node`, if any. */
1561+ private Trait getResolvePathTraitUsed ( RelevantPath path , AssocItemNode node ) {
1562+ exists ( TypeItemNode type , ImplItemNodeImpl impl |
1563+ node = resolvePathCandQualified ( _, type , path , _) and
1564+ typeImplEdge ( type , impl , _, _, node ) and
1565+ result = impl .resolveTraitTyCand ( )
1566+ )
1567+ }
1568+
1569+ private predicate pathTraitUsed ( Element path , Trait trait ) {
1570+ trait = getResolvePathTraitUsed ( path , _)
1571+ }
1572+
15421573/** Gets the item that `path` resolves to, if any. */
15431574cached
15441575ItemNode resolvePath ( RelevantPath path ) {
@@ -1547,9 +1578,9 @@ ItemNode resolvePath(RelevantPath path) {
15471578 (
15481579 // When the result is an associated item of a trait implementation the
15491580 // implemented trait must be visible.
1550- traitIsVisible ( path , assocItemImplementsTrait ( pragma [ only_bind_out ] ( result ) ) )
1581+ TraitIsVisible < pathTraitUsed / 2 > :: traitIsVisible ( path , getResolvePathTraitUsed ( path , result ) )
15511582 or
1552- not exists ( ImplItemNode impl | impl . getAnAssocItem ( ) = result and impl . ( Impl ) . hasTrait ( ) )
1583+ not exists ( getResolvePathTraitUsed ( path , result ) )
15531584 )
15541585 or
15551586 // if `path` is the qualifier of a resolvable `parent`, then we should
@@ -1663,6 +1694,18 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
16631694 )
16641695}
16651696
1697+ /**
1698+ * Holds if `typeItem` is the implementing type of `impl` and the implementation
1699+ * makes `assoc` available as `name` at `kind`.
1700+ */
1701+ private predicate typeImplEdge (
1702+ TypeItemNode typeItem , ImplItemNodeImpl impl , string name , SuccessorKind kind , AssocItemNode assoc
1703+ ) {
1704+ typeItem = impl .resolveSelfTyCand ( ) and
1705+ assoc = impl .getASuccessor ( name , kind ) and
1706+ kind .isExternalOrBoth ( )
1707+ }
1708+
16661709pragma [ nomagic]
16671710private predicate preludeItem ( string name , ItemNode i ) {
16681711 exists ( Crate stdOrCore , ModuleLikeNode mod , ModuleItemNode prelude , ModuleItemNode rust |
0 commit comments