@@ -73,7 +73,7 @@ final class Namespace extends TNamespace {
7373 * - https://doc.rust-lang.org/reference/visibility-and-privacy.html
7474 * - https://doc.rust-lang.org/reference/names/namespaces.html
7575 */
76- abstract class ItemNode extends AstNode {
76+ abstract class ItemNode extends Locatable {
7777 /** Gets the (original) name of this item. */
7878 abstract string getName ( ) ;
7979
@@ -96,6 +96,18 @@ abstract class ItemNode extends AstNode {
9696 Element getADescendant ( ) {
9797 getImmediateParent ( result ) = this
9898 or
99+ // for path resolution, we pretend that the crate is the immediate parent of the
100+ // entry module/source file, which means that lookup via crate dependencies will
101+ // only happen when inner scopes do not shadow
102+ this =
103+ any ( CrateItemNode c |
104+ // entry module/entry source file
105+ result = c .getModuleNode ( )
106+ or
107+ // entry/transitive source file
108+ result = c .getASourceFile ( )
109+ )
110+ or
99111 exists ( Element mid |
100112 mid = this .getADescendant ( ) and
101113 getImmediateParent ( result ) = mid and
@@ -122,6 +134,10 @@ abstract class ItemNode extends AstNode {
122134 or
123135 useImportEdge ( this , name , result )
124136 or
137+ crateDefEdge ( this , name , result )
138+ or
139+ crateDependencyEdge ( this , name , result )
140+ or
125141 // items made available through `use` are available to nodes that contain the `use`
126142 exists ( UseItemNode use |
127143 use = this .getASuccessorRec ( _) and
@@ -180,7 +196,10 @@ abstract class ItemNode extends AstNode {
180196 this = result .( ImplOrTraitItemNode ) .getAnItemInSelfScope ( )
181197 or
182198 name = "crate" and
183- result .( SourceFileItemNode ) .getFile ( ) = this .getFile ( )
199+ exists ( CrateItemNode crate |
200+ this = crate .getASourceFile ( ) and
201+ result = crate .getModuleNode ( )
202+ )
184203 }
185204
186205 /** Gets the location of this item. */
@@ -214,6 +233,51 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
214233 override TypeParam getTypeParam ( int i ) { none ( ) }
215234}
216235
236+ class CrateItemNode extends ItemNode instanceof Crate {
237+ /**
238+ * Gets the module node that defines this crate.
239+ *
240+ * This is either a source file, when the crate is defined in source code,
241+ * or a module, when the crate is defined in a dependency.
242+ */
243+ pragma [ nomagic]
244+ ModuleLikeNode getModuleNode ( ) {
245+ result = super .getSourceFile ( )
246+ or
247+ not exists ( super .getSourceFile ( ) ) and
248+ result = super .getModule ( )
249+ }
250+
251+ /**
252+ * Gets a source file that belongs to this crate, if any.
253+ *
254+ * This is calculated as those source files that can be reached from the entry
255+ * file of this crate using zero or more `mod` imports, without going through
256+ * the entry point of some other crate.
257+ */
258+ pragma [ nomagic]
259+ SourceFileItemNode getASourceFile ( ) {
260+ result = super .getSourceFile ( )
261+ or
262+ exists ( SourceFileItemNode mid , Module mod |
263+ mid = this .getASourceFile ( ) and
264+ mod .getFile ( ) = mid .getFile ( ) and
265+ fileImport ( mod , result ) and
266+ not result = any ( Crate other ) .getSourceFile ( )
267+ )
268+ }
269+
270+ override string getName ( ) { result = Crate .super .getName ( ) }
271+
272+ override Namespace getNamespace ( ) {
273+ result .isType ( ) // can be referenced with `crate`
274+ }
275+
276+ override Visibility getVisibility ( ) { none ( ) }
277+
278+ override TypeParam getTypeParam ( int i ) { none ( ) }
279+ }
280+
217281/** An item that can occur in a trait or an `impl` block. */
218282abstract private class AssocItemNode extends ItemNode , AssocItem {
219283 /** Holds if this associated item has an implementation. */
@@ -595,6 +659,22 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
595659 )
596660}
597661
662+ /**
663+ * Holds if crate `c` defines the item `i` named `name`.
664+ */
665+ pragma [ nomagic]
666+ private predicate crateDefEdge ( CrateItemNode c , string name , ItemNode i ) {
667+ i = c .getModuleNode ( ) .getASuccessor ( name ) and
668+ i .isPublic ( )
669+ }
670+
671+ /**
672+ * Holds if `source` depends on crate `dep` named `name`.
673+ */
674+ private predicate crateDependencyEdge ( Crate source , string name , CrateItemNode dep ) {
675+ dep = source .getDependency ( name )
676+ }
677+
598678private predicate useTreeDeclares ( UseTree tree , string name ) {
599679 not tree .isGlob ( ) and
600680 not exists ( tree .getUseTreeList ( ) ) and
@@ -832,3 +912,48 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
832912 name != "_"
833913 )
834914}
915+
916+ /** Provides predicates for debugging the path resolution implementation. */
917+ private module Debug {
918+ private Locatable getRelevantLocatable ( ) {
919+ exists ( string filepath , int startline , int startcolumn , int endline , int endcolumn |
920+ result .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn ) and
921+ // filepath.matches("%/compile.rs") and
922+ // startline = 1986
923+ // filepath.matches("%/build_steps/mod.rs") and
924+ // startline = 17
925+ filepath .matches ( "%/main.rs" ) and
926+ startline = 1
927+ )
928+ }
929+
930+ predicate debugUnqualifiedPathLookup ( RelevantPath p , string name , Namespace ns , ItemNode encl ) {
931+ p = getRelevantLocatable ( ) and
932+ unqualifiedPathLookup ( p , name , ns , encl )
933+ }
934+
935+ ItemNode debugResolvePath ( RelevantPath path ) {
936+ path = getRelevantLocatable ( ) and
937+ result = resolvePath ( path )
938+ }
939+
940+ predicate debugUseImportEdge ( Use use , string name , ItemNode item ) {
941+ use = getRelevantLocatable ( ) and
942+ useImportEdge ( use , name , item )
943+ }
944+
945+ ItemNode debugGetASuccessorRec ( ItemNode i , string name ) {
946+ i = getRelevantLocatable ( ) and
947+ result = i .getASuccessor ( name )
948+ }
949+
950+ predicate debugFileImportEdge ( Module mod , string name , ItemNode item ) {
951+ mod = getRelevantLocatable ( ) and
952+ fileImportEdge ( mod , name , item )
953+ }
954+
955+ predicate debugFileImport ( Module m , SourceFile f ) {
956+ m = getRelevantLocatable ( ) and
957+ fileImport ( m , f )
958+ }
959+ }
0 commit comments