@@ -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 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,24 @@ 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 | this = trait |
328+ result = trait .getAssocItem ( name )
329+ or
330+ // a trait has access to the associated items of its supertraits
331+ not trait .hasAssocItem ( name ) and
332+ result = trait .resolveABoundCand ( ) .getASuccessor ( name ) .( AssocItemNode )
333+ ) and
334+ kind .isExternal ( ) and
335+ useOpt .isNone ( )
338336 or
339337 // 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- )
338+ typeImplEdge ( this , _, name , result ) and
339+ kind .isExternal ( ) and
340+ useOpt .isNone ( )
341+ or
342+ implEdge ( this , name , result ) and
343+ kind .isExternal ( ) and
344+ useOpt .isNone ( )
354345 or
355346 // type parameters have access to the associated items of its bounds
356347 result =
@@ -413,14 +404,8 @@ abstract class ItemNode extends Locatable {
413404 this instanceof SourceFile and
414405 builtin ( name , result )
415406 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- )
407+ name = "Self" and
408+ this = result .( ImplOrTraitItemNode ) .getAnItemInSelfScope ( )
424409 or
425410 name = "crate" and
426411 this = result .( CrateItemNode ) .getASourceFile ( )
@@ -755,7 +740,7 @@ abstract class ImplOrTraitItemNode extends ItemNode {
755740 }
756741
757742 /** Gets an associated item belonging to this trait or `impl` block. */
758- abstract AssocItemNode getAnAssocItem ( ) ;
743+ AssocItemNode getAnAssocItem ( ) { result = this . getADescendant ( ) }
759744
760745 /** Gets the associated item named `name` belonging to this trait or `impl` block. */
761746 pragma [ nomagic]
@@ -807,8 +792,6 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
807792
808793 TraitItemNode resolveTraitTy ( ) { result = resolvePath ( this .getTraitPath ( ) ) }
809794
810- override AssocItemNode getAnAssocItem ( ) { result = this .getADescendant ( ) }
811-
812795 override string getName ( ) { result = "(impl)" }
813796
814797 override Namespace getNamespace ( ) {
@@ -985,6 +968,18 @@ private class ImplItemNodeImpl extends ImplItemNode {
985968 }
986969
987970 TraitItemNodeImpl resolveTraitTyCand ( ) { result = resolvePathCand ( this .getTraitPath ( ) ) }
971+
972+ /**
973+ * Gets the associated item named `name` in this impl block or the default
974+ * inherited from the trait being implemented.
975+ */
976+ AssocItemNode getAssocItemOrDefault ( string name ) {
977+ result = this .getAssocItem ( name )
978+ or
979+ not this .hasAssocItem ( name ) and
980+ result = this .resolveTraitTyCand ( ) .getAssocItem ( name ) and
981+ result .hasImplementation ( )
982+ }
988983}
989984
990985private class StructItemNode extends TypeItemTypeItemNode , ParameterizableItemNode instanceof Struct
@@ -1020,8 +1015,6 @@ final class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof T
10201015
10211016 ItemNode resolveABound ( ) { result = this .resolveBound ( _) }
10221017
1023- override AssocItemNode getAnAssocItem ( ) { result = this .getADescendant ( ) }
1024-
10251018 override string getName ( ) { result = Trait .super .getName ( ) .getText ( ) }
10261019
10271020 override Namespace getNamespace ( ) { result .isType ( ) }
@@ -1852,35 +1845,12 @@ private predicate checkQualifiedVisibility(
18521845 not i instanceof TypeParam
18531846}
18541847
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-
18721848/**
18731849 * Gets the item that `path` resolves to in `ns` when `qualifier` is the
18741850 * qualifier of `path` and `qualifier` resolves to `q`, if any.
18751851 */
18761852pragma [ nomagic]
18771853private 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
18841854 exists ( string name , SuccessorKind kind , UseOption useOpt |
18851855 q = resolvePathCandQualifier ( qualifier , path , name ) and
18861856 result = getASuccessor ( q , name , ns , kind , useOpt ) and
@@ -1940,6 +1910,37 @@ private predicate macroExportEdge(CrateItemNode crate, string name, MacroItemNod
19401910 name = macro .getName ( )
19411911}
19421912
1913+ /**
1914+ * Holds if a `Self` path inside `impl` might refer to a function named `name`
1915+ * from another impl block.
1916+ */
1917+ pragma [ nomagic]
1918+ private predicate relevantSelfFunctionName ( ImplItemNodeImpl impl , string name ) {
1919+ any ( Path path | path .getQualifier ( ) = impl .getASelfPath ( ) ) .getText ( ) = name and
1920+ not impl .hasAssocItem ( name )
1921+ }
1922+
1923+ /**
1924+ * Holds if `impl` has a `node` available externally at `name`.
1925+ *
1926+ * Since `Self` in an impl block resolves to the impl block, this corresponds to
1927+ * the items that should be available on `Self` within the `impl` block.
1928+ */
1929+ private predicate implEdge ( ImplItemNodeImpl impl , string name , AssocItemNode node ) {
1930+ node = impl .getAssocItemOrDefault ( name )
1931+ or
1932+ // Associated types from the implemented trait are available on `Self`.
1933+ not impl .hasAssocItem ( name ) and
1934+ node = impl .resolveTraitTyCand ( ) .getASuccessor ( name ) .( TypeAliasItemNode )
1935+ or
1936+ // Items available on the implementing type are available on `Self`. We only
1937+ // add these edges when they are relevant. If a type has `n` impl blocks with
1938+ // `m` functions each, we would otherwise end up always constructing somethong
1939+ // proportional to `O(n * m)`.
1940+ relevantSelfFunctionName ( impl , name ) and
1941+ node = impl .resolveSelfTyCand ( ) .getASuccessor ( name )
1942+ }
1943+
19431944/**
19441945 * Holds if item `i` contains a `mod` or `extern crate` definition that
19451946 * makes the macro `macro` named `name` available using a `#[macro_use]`
@@ -1984,7 +1985,9 @@ private ItemNode resolvePathCand(PathExt path) {
19841985 then result instanceof TraitItemNode
19851986 else
19861987 if path = any ( PathTypeRepr p ) .getPath ( )
1987- then result instanceof TypeItemNode
1988+ then
1989+ result instanceof TypeItemNode or
1990+ result instanceof ImplItemNodeImpl
19881991 else
19891992 if path instanceof IdentPat
19901993 then
@@ -2011,7 +2014,7 @@ private ItemNode resolvePathCand(PathExt path) {
20112014private Trait getResolvePathTraitUsed ( PathExt path , AssocItemNode node ) {
20122015 exists ( TypeItemNode type , ImplItemNodeImpl impl |
20132016 node = resolvePathCandQualified ( _, type , path , _) and
2014- typeImplEdge ( type , impl , _, _ , node , _ ) and
2017+ typeImplEdge ( type , impl , _, node ) and
20152018 result = impl .resolveTraitTyCand ( )
20162019 )
20172020}
@@ -2182,12 +2185,14 @@ private predicate externCrateEdge(
21822185 * makes `assoc` available as `name` at `kind`.
21832186 */
21842187private predicate typeImplEdge (
2185- TypeItemNode typeItem , ImplItemNodeImpl impl , string name , SuccessorKind kind ,
2186- AssocItemNode assoc , UseOption useOpt
2188+ TypeItemNode typeItem , ImplItemNodeImpl impl , string name , AssocItemNode assoc
21872189) {
2190+ assoc = impl .getAssocItemOrDefault ( name ) and
21882191 typeItem = impl .resolveSelfTyCand ( ) and
2189- assoc = impl .getASuccessor ( name , kind , useOpt ) and
2190- kind .isExternalOrBoth ( )
2192+ // Functions in `impl` blocks are made available on the implementing type
2193+ // (e.g., `S::fun` is valid) but associated types are not (e.g., `S::Output`
2194+ // is invalid).
2195+ ( assoc instanceof FunctionItemNode or assoc instanceof ConstItemNode )
21912196}
21922197
21932198pragma [ nomagic]
0 commit comments