Skip to content

Commit 34264fe

Browse files
committed
Rust: Cross-crate path resolution
1 parent 5f53eff commit 34264fe

4 files changed

Lines changed: 125 additions & 6 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use lib::a_module::hello; // $ MISSING: item=HELLO
1+
use lib::a_module::hello; // $ item=HELLO
22

33
mod a_module;
44

55
fn main() {
6-
hello(); // $ MISSING: item=HELLO
6+
hello(); // $ item=HELLO
77
}

rust/ql/lib/codeql/rust/elements/internal/CrateImpl.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ private import codeql.rust.elements.internal.generated.Crate
1212
*/
1313
module Impl {
1414
private import rust
15+
private import codeql.rust.internal.PathResolution
1516

1617
class Crate extends Generated::Crate {
1718
override string toStringImpl() {
@@ -30,6 +31,14 @@ module Impl {
3031
i = 4 and result = ")"
3132
}
3233

34+
/** Gets the source file that defines this crate, if any. */
35+
SourceFile getSourceFile() { result.getFile() = this.getModule().getFile() }
36+
37+
/**
38+
* Gets a source file that belongs to this crate, if any.
39+
*/
40+
SourceFile getASourceFile() { result = this.(CrateItemNode).getASourceFile() }
41+
3342
override Location getLocation() { result = this.getModule().getLocation() }
3443
}
3544
}

rust/ql/lib/codeql/rust/internal/PathResolution.qll

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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,7 @@ abstract class ItemNode extends AstNode {
180184
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
181185
or
182186
name = "crate" and
183-
result.(SourceFileItemNode).getFile() = this.getFile()
187+
this = result.(Crate).getASourceFile()
184188
}
185189

186190
/** Gets the location of this item. */
@@ -214,6 +218,46 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
214218
override TypeParam getTypeParam(int i) { none() }
215219
}
216220

221+
class CrateItemNode extends ItemNode instanceof Crate {
222+
/** Gets the module node that defines this crate. */
223+
pragma[nomagic]
224+
ModuleLikeNode getModuleNode() {
225+
result = super.getSourceFile()
226+
or
227+
not exists(super.getSourceFile()) and
228+
result = super.getModule()
229+
}
230+
231+
/**
232+
* Gets a source file that belongs to this crate, if any.
233+
*
234+
* This is calculated as those source files that can be reached from the entry
235+
* file of this crate using zero or more `mod` imports, without going through
236+
* the entry point of some other crate.
237+
*/
238+
pragma[nomagic]
239+
SourceFileItemNode getASourceFile() {
240+
result = super.getSourceFile()
241+
or
242+
exists(SourceFileItemNode mid, Module mod |
243+
mid = this.getASourceFile() and
244+
mod.getFile() = mid.getFile() and
245+
fileImport(mod, result) and
246+
not result = any(Crate other).getSourceFile()
247+
)
248+
}
249+
250+
override string getName() { result = "(crate)" }
251+
252+
override Namespace getNamespace() {
253+
result.isType() // can be referenced with `crate`
254+
}
255+
256+
override Visibility getVisibility() { none() }
257+
258+
override TypeParam getTypeParam(int i) { none() }
259+
}
260+
217261
/** An item that can occur in a trait or an `impl` block. */
218262
abstract private class AssocItemNode extends ItemNode, AssocItem {
219263
/** Holds if this associated item has an implementation. */
@@ -600,6 +644,31 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
600644
)
601645
}
602646

647+
/**
648+
* Holds if crate `c` defines the item `i` named `name`.
649+
*/
650+
pragma[nomagic]
651+
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
652+
i = c.getModuleNode().getASuccessor(name)
653+
}
654+
655+
/**
656+
* Holds if `source` depends on crate `dep` named `name`.
657+
*
658+
* Does not yet take dependency renaming into account.
659+
*/
660+
pragma[nomagic]
661+
private predicate crateDependencyEdge(ModuleLikeNode source, string name, Crate dep) {
662+
exists(CrateItemNode c |
663+
dep = c.(Crate).getADependency() and
664+
dep.getName() = name
665+
|
666+
source = c.getModuleNode()
667+
or
668+
source = c.(Crate).getASourceFile()
669+
)
670+
}
671+
603672
private predicate useTreeDeclares(UseTree tree, string name) {
604673
not tree.isGlob() and
605674
not exists(tree.getUseTreeList()) and
@@ -837,3 +906,44 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
837906
name != "_"
838907
)
839908
}
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("%/build_steps/mod.rs") and
916+
startline = 17
917+
)
918+
}
919+
920+
ItemNode debugResolvePath(RelevantPath path) {
921+
path = getRelevantLocatable() and
922+
result = resolvePath(path)
923+
}
924+
925+
predicate debugCrateDependencyEdge(ModuleLikeNode source, string name, Crate dep) {
926+
source = getRelevantLocatable() and
927+
crateDependencyEdge(source, name, dep)
928+
}
929+
930+
predicate debugUseImportEdge(Use use, string name, ItemNode item) {
931+
use = getRelevantLocatable() and
932+
useImportEdge(use, name, item)
933+
}
934+
935+
ItemNode debugGetASuccessorRec(ItemNode i, string name) {
936+
i = getRelevantLocatable() and
937+
result = i.getASuccessor(name)
938+
}
939+
940+
predicate debugFileImportEdge(Module mod, string name, ItemNode item) {
941+
mod = getRelevantLocatable() and
942+
fileImportEdge(mod, name, item)
943+
}
944+
945+
predicate debugFileImport(Module m, SourceFile f) {
946+
m = getRelevantLocatable() and
947+
fileImport(m, f)
948+
}
949+
}

rust/ql/test/library-tests/path-resolution/path-resolution.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ resolvePath
129129
| main.rs:274:16:274:16 | T | main.rs:268:7:268:7 | T |
130130
| main.rs:275:14:275:17 | Self | main.rs:266:5:276:5 | trait MyParamTrait |
131131
| main.rs:275:14:275:33 | ...::AssociatedType | main.rs:270:9:270:28 | TypeAlias |
132-
| main.rs:284:13:284:17 | crate | main.rs:1:1:499:2 | SourceFile |
132+
| main.rs:284:13:284:17 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
133133
| main.rs:284:13:284:22 | ...::m13 | main.rs:279:1:292:1 | mod m13 |
134134
| main.rs:284:13:284:25 | ...::f | main.rs:280:5:280:17 | fn f |
135135
| main.rs:284:13:284:25 | ...::f | main.rs:280:19:281:19 | struct f |
@@ -220,7 +220,7 @@ resolvePath
220220
| main.rs:479:5:479:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
221221
| main.rs:480:5:480:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
222222
| main.rs:481:5:481:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
223-
| main.rs:482:5:482:9 | crate | main.rs:1:1:499:2 | SourceFile |
223+
| main.rs:482:5:482:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
224224
| main.rs:482:5:482:12 | ...::h | main.rs:50:1:69:1 | fn h |
225225
| main.rs:483:5:483:6 | m1 | main.rs:13:1:37:1 | mod m1 |
226226
| main.rs:483:5:483:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |

0 commit comments

Comments
 (0)