@@ -110,18 +110,15 @@ pragma[nomagic]
110110private ItemNode getAChildSuccessor ( ItemNode item , string name , SuccessorKind kind ) {
111111 item = result .getImmediateParent ( ) and
112112 name = result .getName ( ) and
113+ // Associated types in `impl` and `trait` blocks are only handled elsewhere
114+ not ( item instanceof ImplOrTraitItemNode and result instanceof AssocItem ) and
113115 // type parameters are only available inside the declaring item
114116 if result instanceof TypeParam
115117 then kind .isInternal ( )
116118 else
117- // associated items must always be qualified, also within the declaring
118- // item (using `Self`)
119- if item instanceof ImplOrTraitItemNode and result instanceof AssocItem
120- then kind .isExternal ( )
121- else
122- if result .isPublic ( )
123- then kind .isBoth ( )
124- else kind .isInternal ( )
119+ if result .isPublic ( )
120+ then kind .isBoth ( )
121+ else kind .isInternal ( )
125122}
126123
127124private module UseOption = Option< Use > ;
@@ -327,30 +324,26 @@ abstract class ItemNode extends Locatable {
327324 )
328325 )
329326 or
330- // a trait has access to the associated items of its supertraits
331- this =
332- any ( TraitItemNodeImpl trait |
333- result = trait .resolveABoundCand ( ) .getASuccessor ( name , kind , useOpt ) and
334- kind .isExternalOrBoth ( ) and
335- result instanceof AssocItemNode and
336- not trait .hasAssocItem ( name )
337- )
327+ exists ( TraitItemNodeImpl trait |
328+ this = trait and
329+ kind .isExternal ( ) and
330+ useOpt .isNone ( )
331+ |
332+ result = trait .getAssocItem ( name )
333+ or
334+ // a trait has access to the associated items of its supertraits
335+ not trait .hasAssocItem ( name ) and
336+ result = trait .resolveABoundCand ( ) .getASuccessor ( name ) .( AssocItemNode )
337+ )
338338 or
339339 // items made available by an implementation where `this` is the implementing type
340- typeImplEdge ( this , _, name , kind , result , useOpt )
341- or
342- // trait items with default implementations made available in an implementation
343- exists ( ImplItemNodeImpl impl , TraitItemNode trait |
344- this = impl and
345- trait = impl .resolveTraitTyCand ( ) and
346- result = trait .getASuccessor ( name , kind , useOpt ) and
347- // do not inherit default implementations from super traits; those are inherited by
348- // their `impl` blocks
349- result = trait .getAssocItem ( name ) and
350- result .( AssocItemNode ) .hasImplementation ( ) and
351- kind .isExternalOrBoth ( ) and
352- not impl .hasAssocItem ( name )
353- )
340+ typeImplEdge ( this , _, name , result ) and
341+ kind .isExternal ( ) and
342+ useOpt .isNone ( )
343+ or
344+ implEdge ( this , name , result ) and
345+ kind .isExternal ( ) and
346+ useOpt .isNone ( )
354347 or
355348 // type parameters have access to the associated items of its bounds
356349 result =
@@ -413,14 +406,8 @@ abstract class ItemNode extends Locatable {
413406 this instanceof SourceFile and
414407 builtin ( name , result )
415408 or
416- exists ( ImplOrTraitItemNode i |
417- name = "Self" and
418- this = i .getAnItemInSelfScope ( )
419- |
420- result = i .( Trait )
421- or
422- result = i .( ImplItemNodeImpl ) .resolveSelfTyCand ( )
423- )
409+ name = "Self" and
410+ this = result .( ImplOrTraitItemNode ) .getAnItemInSelfScope ( )
424411 or
425412 name = "crate" and
426413 this = result .( CrateItemNode ) .getASourceFile ( )
@@ -755,7 +742,7 @@ abstract class ImplOrTraitItemNode extends ItemNode {
755742 }
756743
757744 /** Gets an associated item belonging to this trait or `impl` block. */
758- abstract AssocItemNode getAnAssocItem ( ) ;
745+ AssocItemNode getAnAssocItem ( ) { result = this . getADescendant ( ) }
759746
760747 /** Gets the associated item named `name` belonging to this trait or `impl` block. */
761748 pragma [ nomagic]
@@ -807,8 +794,6 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
807794
808795 TraitItemNode resolveTraitTy ( ) { result = resolvePath ( this .getTraitPath ( ) ) }
809796
810- override AssocItemNode getAnAssocItem ( ) { result = this .getADescendant ( ) }
811-
812797 override string getName ( ) { result = "(impl)" }
813798
814799 override Namespace getNamespace ( ) {
@@ -985,6 +970,18 @@ private class ImplItemNodeImpl extends ImplItemNode {
985970 }
986971
987972 TraitItemNodeImpl resolveTraitTyCand ( ) { result = resolvePathCand ( this .getTraitPath ( ) ) }
973+
974+ /**
975+ * Gets the associated item named `name` in this impl block or the default
976+ * inherited from the trait being implemented.
977+ */
978+ AssocItemNode getAssocItemOrDefault ( string name ) {
979+ result = this .getAssocItem ( name )
980+ or
981+ not this .hasAssocItem ( name ) and
982+ result = this .resolveTraitTyCand ( ) .getAssocItem ( name ) and
983+ result .hasImplementation ( )
984+ }
988985}
989986
990987private class StructItemNode extends TypeItemTypeItemNode , ParameterizableItemNode instanceof Struct
@@ -1020,8 +1017,6 @@ final class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof T
10201017
10211018 ItemNode resolveABound ( ) { result = this .resolveBound ( _) }
10221019
1023- override AssocItemNode getAnAssocItem ( ) { result = this .getADescendant ( ) }
1024-
10251020 override string getName ( ) { result = Trait .super .getName ( ) .getText ( ) }
10261021
10271022 override Namespace getNamespace ( ) { result .isType ( ) }
@@ -1852,35 +1847,12 @@ private predicate checkQualifiedVisibility(
18521847 not i instanceof TypeParam
18531848}
18541849
1855- pragma [ nomagic]
1856- private predicate isImplSelfQualifiedPath (
1857- ImplItemNode impl , PathExt qualifier , PathExt path , string name
1858- ) {
1859- qualifier = impl .getASelfPath ( ) and
1860- qualifier = path .getQualifier ( ) and
1861- name = path .getText ( )
1862- }
1863-
1864- private ItemNode resolveImplSelfQualified ( PathExt qualifier , PathExt path , Namespace ns ) {
1865- exists ( ImplItemNode impl , string name |
1866- isImplSelfQualifiedPath ( impl , qualifier , path , name ) and
1867- result = impl .getAssocItem ( name ) and
1868- ns = result .getNamespace ( )
1869- )
1870- }
1871-
18721850/**
18731851 * Gets the item that `path` resolves to in `ns` when `qualifier` is the
18741852 * qualifier of `path` and `qualifier` resolves to `q`, if any.
18751853 */
18761854pragma [ nomagic]
18771855private ItemNode resolvePathCandQualified ( PathExt qualifier , ItemNode q , PathExt path , Namespace ns ) {
1878- // Special case for `Self::Assoc`; this always refers to the associated
1879- // item in the enclosing `impl` block, if available.
1880- q = resolvePathCandQualifier ( qualifier , path , _) and
1881- result = resolveImplSelfQualified ( qualifier , path , ns )
1882- or
1883- not exists ( resolveImplSelfQualified ( qualifier , path , ns ) ) and
18841856 exists ( string name , SuccessorKind kind , UseOption useOpt |
18851857 q = resolvePathCandQualifier ( qualifier , path , name ) and
18861858 result = getASuccessor ( q , name , ns , kind , useOpt ) and
@@ -1940,6 +1912,37 @@ private predicate macroExportEdge(CrateItemNode crate, string name, MacroItemNod
19401912 name = macro .getName ( )
19411913}
19421914
1915+ /**
1916+ * Holds if a `Self` path inside `impl` might refer to a function named `name`
1917+ * from another impl block.
1918+ */
1919+ pragma [ nomagic]
1920+ private predicate relevantSelfFunctionName ( ImplItemNodeImpl impl , string name ) {
1921+ any ( Path path | path .getQualifier ( ) = impl .getASelfPath ( ) ) .getText ( ) = name and
1922+ not impl .hasAssocItem ( name )
1923+ }
1924+
1925+ /**
1926+ * Holds if `impl` has a `node` available externally at `name`.
1927+ *
1928+ * Since `Self` in an impl block resolves to the impl block, this corresponds to
1929+ * the items that should be available on `Self` within the `impl` block.
1930+ */
1931+ private predicate implEdge ( ImplItemNodeImpl impl , string name , AssocItemNode node ) {
1932+ node = impl .getAssocItemOrDefault ( name )
1933+ or
1934+ // Associated types from the implemented trait are available on `Self`.
1935+ not impl .hasAssocItem ( name ) and
1936+ node = impl .resolveTraitTyCand ( ) .getASuccessor ( name ) .( TypeAliasItemNode )
1937+ or
1938+ // Items available on the implementing type are available on `Self`. We only
1939+ // add these edges when they are relevant. If a type has `n` impl blocks with
1940+ // `m` functions each, we would otherwise end up always constructing somethong
1941+ // proportional to `O(n * m)`.
1942+ relevantSelfFunctionName ( impl , name ) and
1943+ node = impl .resolveSelfTyCand ( ) .getASuccessor ( name )
1944+ }
1945+
19431946/**
19441947 * Holds if item `i` contains a `mod` or `extern crate` definition that
19451948 * makes the macro `macro` named `name` available using a `#[macro_use]`
@@ -1984,7 +1987,9 @@ private ItemNode resolvePathCand(PathExt path) {
19841987 then result instanceof TraitItemNode
19851988 else
19861989 if path = any ( PathTypeRepr p ) .getPath ( )
1987- then result instanceof TypeItemNode
1990+ then
1991+ result instanceof TypeItemNode or
1992+ result instanceof ImplItemNodeImpl
19881993 else
19891994 if path instanceof IdentPat
19901995 then
@@ -2011,7 +2016,7 @@ private ItemNode resolvePathCand(PathExt path) {
20112016private Trait getResolvePathTraitUsed ( PathExt path , AssocItemNode node ) {
20122017 exists ( TypeItemNode type , ImplItemNodeImpl impl |
20132018 node = resolvePathCandQualified ( _, type , path , _) and
2014- typeImplEdge ( type , impl , _, _ , node , _ ) and
2019+ typeImplEdge ( type , impl , _, node ) and
20152020 result = impl .resolveTraitTyCand ( )
20162021 )
20172022}
@@ -2182,12 +2187,14 @@ private predicate externCrateEdge(
21822187 * makes `assoc` available as `name` at `kind`.
21832188 */
21842189private predicate typeImplEdge (
2185- TypeItemNode typeItem , ImplItemNodeImpl impl , string name , SuccessorKind kind ,
2186- AssocItemNode assoc , UseOption useOpt
2190+ TypeItemNode typeItem , ImplItemNodeImpl impl , string name , AssocItemNode assoc
21872191) {
2192+ assoc = impl .getAssocItemOrDefault ( name ) and
21882193 typeItem = impl .resolveSelfTyCand ( ) and
2189- assoc = impl .getASuccessor ( name , kind , useOpt ) and
2190- kind .isExternalOrBoth ( )
2194+ // Functions in `impl` blocks are made available on the implementing type
2195+ // (e.g., `S::fun` is valid) but associated types are not (e.g., `S::Output`
2196+ // is invalid).
2197+ ( assoc instanceof FunctionItemNode or assoc instanceof ConstItemNode )
21912198}
21922199
21932200pragma [ nomagic]
0 commit comments