@@ -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
@@ -122,6 +122,10 @@ abstract class ItemNode extends AstNode {
122122 or
123123 useImportEdge ( this , name , result )
124124 or
125+ crateDefEdge ( this , name , result )
126+ or
127+ crateDependencyEdge ( this , name , result )
128+ or
125129 // items made available through `use` are available to nodes that contain the `use`
126130 exists ( UseItemNode use |
127131 use = this .getASuccessorRec ( _) and
@@ -180,7 +184,10 @@ abstract class ItemNode extends AstNode {
180184 this = result .( ImplOrTraitItemNode ) .getAnItemInSelfScope ( )
181185 or
182186 name = "crate" and
183- result .( SourceFileItemNode ) .getFile ( ) = this .getFile ( )
187+ exists ( CrateItemNode crate |
188+ this = crate .getASourceFile ( ) and
189+ result = crate .getModuleNode ( )
190+ )
184191 }
185192
186193 /** Gets the location of this item. */
@@ -214,6 +221,51 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
214221 override TypeParam getTypeParam ( int i ) { none ( ) }
215222}
216223
224+ class CrateItemNode extends ItemNode instanceof Crate {
225+ /**
226+ * Gets the module node that defines this crate.
227+ *
228+ * This is either a source file, when the crate is defined in source code,
229+ * or a module, when the crate is defined in a dependency.
230+ */
231+ pragma [ nomagic]
232+ ModuleLikeNode getModuleNode ( ) {
233+ result = super .getSourceFile ( )
234+ or
235+ not exists ( super .getSourceFile ( ) ) and
236+ result = super .getModule ( )
237+ }
238+
239+ /**
240+ * Gets a source file that belongs to this crate, if any.
241+ *
242+ * This is calculated as those source files that can be reached from the entry
243+ * file of this crate using zero or more `mod` imports, without going through
244+ * the entry point of some other crate.
245+ */
246+ pragma [ nomagic]
247+ SourceFileItemNode getASourceFile ( ) {
248+ result = super .getSourceFile ( )
249+ or
250+ exists ( SourceFileItemNode mid , Module mod |
251+ mid = this .getASourceFile ( ) and
252+ mod .getFile ( ) = mid .getFile ( ) and
253+ fileImport ( mod , result ) and
254+ not result = any ( Crate other ) .getSourceFile ( )
255+ )
256+ }
257+
258+ override string getName ( ) { result = Crate .super .getName ( ) }
259+
260+ override Namespace getNamespace ( ) {
261+ result .isType ( ) // can be referenced with `crate`
262+ }
263+
264+ override Visibility getVisibility ( ) { none ( ) }
265+
266+ override TypeParam getTypeParam ( int i ) { none ( ) }
267+ }
268+
217269/** An item that can occur in a trait or an `impl` block. */
218270abstract private class AssocItemNode extends ItemNode , AssocItem {
219271 /** Holds if this associated item has an implementation. */
@@ -595,6 +647,28 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
595647 )
596648}
597649
650+ /**
651+ * Holds if crate `c` defines the item `i` named `name`.
652+ */
653+ pragma [ nomagic]
654+ private predicate crateDefEdge ( CrateItemNode c , string name , ItemNode i ) {
655+ i = c .getModuleNode ( ) .getASuccessor ( name ) and
656+ i .isPublic ( )
657+ }
658+
659+ /**
660+ * Holds if `m` depends on crate `dep` named `name`.
661+ */
662+ private predicate crateDependencyEdge ( ModuleLikeNode m , string name , CrateItemNode dep ) {
663+ exists ( CrateItemNode c | dep = c .( Crate ) .getDependency ( name ) |
664+ // entry module/entry source file
665+ m = c .getModuleNode ( )
666+ or
667+ // entry/transitive source file
668+ m = c .getASourceFile ( )
669+ )
670+ }
671+
598672private predicate useTreeDeclares ( UseTree tree , string name ) {
599673 not tree .isGlob ( ) and
600674 not exists ( tree .getUseTreeList ( ) ) and
@@ -832,3 +906,48 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
832906 name != "_"
833907 )
834908}
909+
910+ /** Provides predicates for debugging the path resolution implementation. */
911+ private module Debug {
912+ private Locatable getRelevantLocatable ( ) {
913+ exists ( string filepath , int startline , int startcolumn , int endline , int endcolumn |
914+ result .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn ) and
915+ // filepath.matches("%/compile.rs") and
916+ // startline = 1986
917+ // filepath.matches("%/build_steps/mod.rs") and
918+ // startline = 17
919+ filepath .matches ( "%/main.rs" ) and
920+ startline = 1
921+ )
922+ }
923+
924+ predicate debugUnqualifiedPathLookup ( RelevantPath p , string name , Namespace ns , ItemNode encl ) {
925+ p = getRelevantLocatable ( ) and
926+ unqualifiedPathLookup ( p , name , ns , encl )
927+ }
928+
929+ ItemNode debugResolvePath ( RelevantPath path ) {
930+ path = getRelevantLocatable ( ) and
931+ result = resolvePath ( path )
932+ }
933+
934+ predicate debugUseImportEdge ( Use use , string name , ItemNode item ) {
935+ use = getRelevantLocatable ( ) and
936+ useImportEdge ( use , name , item )
937+ }
938+
939+ ItemNode debugGetASuccessorRec ( ItemNode i , string name ) {
940+ i = getRelevantLocatable ( ) and
941+ result = i .getASuccessor ( name )
942+ }
943+
944+ predicate debugFileImportEdge ( Module mod , string name , ItemNode item ) {
945+ mod = getRelevantLocatable ( ) and
946+ fileImportEdge ( mod , name , item )
947+ }
948+
949+ predicate debugFileImport ( Module m , SourceFile f ) {
950+ m = getRelevantLocatable ( ) and
951+ fileImport ( m , f )
952+ }
953+ }
0 commit comments