Skip to content

Commit 425fa0d

Browse files
authored
Merge pull request #18823 from hvitved/rust/path-resolution-more
Rust: More path resolution improvements
2 parents fcb4703 + 7380ec8 commit 425fa0d

File tree

3 files changed

+202
-87
lines changed

3 files changed

+202
-87
lines changed

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

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,31 @@ abstract class ItemNode extends AstNode {
132132
)
133133
or
134134
// a trait has access to the associated items of its supertraits
135-
result = this.(TraitItemNode).resolveABound().getASuccessorRec(name) and
136-
result instanceof AssocItemNode
135+
this =
136+
any(TraitItemNode trait |
137+
result = trait.resolveABound().getASuccessorRec(name) and
138+
result instanceof AssocItemNode and
139+
not trait.hasAssocItem(name)
140+
)
137141
or
138142
// items made available by an implementation where `this` is the implementing type
139143
exists(ItemNode node |
140144
this = node.(ImplItemNode).resolveSelfTy() and
141145
result = node.getASuccessorRec(name) and
142146
result instanceof AssocItemNode
143147
)
148+
or
149+
// trait items with default implementations made available in an implementation
150+
exists(ImplItemNode impl, ItemNode trait |
151+
this = impl and
152+
trait = impl.resolveTraitTy() and
153+
result = trait.getASuccessorRec(name) and
154+
result.(AssocItemNode).hasImplementation() and
155+
not impl.hasAssocItem(name)
156+
)
157+
or
158+
// type parameters have access to the associated items of its bounds
159+
result = this.(TypeParamItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
144160
}
145161

146162
/** Gets a successor named `name` of this item, if any. */
@@ -163,6 +179,9 @@ abstract class ItemNode extends AstNode {
163179
name = "crate" and
164180
result.(SourceFileItemNode).getFile() = this.getFile()
165181
}
182+
183+
/** Gets the location of this item. */
184+
Location getLocation() { result = super.getLocation() }
166185
}
167186

168187
/** A module or a source file. */
@@ -191,11 +210,16 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
191210
}
192211

193212
/** An item that can occur in a trait or an `impl` block. */
194-
abstract private class AssocItemNode extends ItemNode { }
213+
abstract private class AssocItemNode extends ItemNode, AssocItem {
214+
/** Holds if this associated item has an implementation. */
215+
abstract predicate hasImplementation();
216+
}
195217

196218
private class ConstItemNode extends AssocItemNode instanceof Const {
197219
override string getName() { result = Const.super.getName().getText() }
198220

221+
override predicate hasImplementation() { super.hasBody() }
222+
199223
override Namespace getNamespace() { result.isValue() }
200224

201225
override Visibility getVisibility() { result = Const.super.getVisibility() }
@@ -219,9 +243,11 @@ private class VariantItemNode extends ItemNode instanceof Variant {
219243
override Visibility getVisibility() { result = Variant.super.getVisibility() }
220244
}
221245

222-
private class FunctionItemNode extends AssocItemNode instanceof Function {
246+
class FunctionItemNode extends AssocItemNode instanceof Function {
223247
override string getName() { result = Function.super.getName().getText() }
224248

249+
override predicate hasImplementation() { super.hasBody() }
250+
225251
override Namespace getNamespace() { result.isValue() }
226252

227253
override Visibility getVisibility() { result = Function.super.getVisibility() }
@@ -242,7 +268,19 @@ abstract private class ImplOrTraitItemNode extends ItemNode {
242268
}
243269

244270
class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
245-
ItemNode resolveSelfTy() { result = resolvePath(super.getSelfTy().(PathTypeRepr).getPath()) }
271+
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
272+
273+
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
274+
275+
ItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
276+
277+
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
278+
279+
/** Holds if this `impl` block declares an associated item named `name`. */
280+
pragma[nomagic]
281+
predicate hasAssocItem(string name) {
282+
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
283+
}
246284

247285
override string getName() { result = "(impl)" }
248286

@@ -256,6 +294,8 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
256294
private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
257295
override string getName() { result = "(macro call)" }
258296

297+
override predicate hasImplementation() { none() }
298+
259299
override Namespace getNamespace() { none() }
260300

261301
override Visibility getVisibility() { none() }
@@ -290,6 +330,12 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
290330

291331
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
292332

333+
/** Holds if this trait declares an associated item named `name`. */
334+
pragma[nomagic]
335+
predicate hasAssocItem(string name) {
336+
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
337+
}
338+
293339
override string getName() { result = Trait.super.getName().getText() }
294340

295341
override Namespace getNamespace() { result.isType() }
@@ -300,6 +346,8 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
300346
class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
301347
override string getName() { result = TypeAlias.super.getName().getText() }
302348

349+
override predicate hasImplementation() { super.hasTypeRepr() }
350+
303351
override Namespace getNamespace() { result.isType() }
304352

305353
override Visibility getVisibility() { result = TypeAlias.super.getVisibility() }
@@ -330,11 +378,20 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
330378
}
331379

332380
private class TypeParamItemNode extends ItemNode instanceof TypeParam {
381+
pragma[nomagic]
382+
Path getABoundPath() {
383+
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
384+
}
385+
386+
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
387+
333388
override string getName() { result = TypeParam.super.getName().getText() }
334389

335390
override Namespace getNamespace() { result.isType() }
336391

337392
override Visibility getVisibility() { none() }
393+
394+
override Location getLocation() { result = TypeParam.super.getName().getLocation() }
338395
}
339396

340397
/** Holds if `item` has the name `name` and is a top-level item inside `f`. */

rust/ql/test/library-tests/path-resolution/main.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ mod m16 {
357357
fn g(&self) -> T // $ item=I84
358358
; // I85
359359

360+
fn h(&self) -> T { // $ item=I84
361+
Self::g(&self); // $ item=I85
362+
self.g() // $ MISSING: item=I85
363+
} // I96
364+
360365
const c: T // $ item=I84
361366
; // I94
362367
} // I86
@@ -425,6 +430,8 @@ mod m16 {
425430
>::f(&x); // $ MISSING: item=I93
426431
S::g(&x); // $ item=I92
427432
x.g(); // $ MISSING: item=I92
433+
S::h(&x); // $ item=I96
434+
x.h(); // $ MISSING: item=I96
428435
S::c; // $ item=I95
429436
<S // $ item=I90
430437
as Trait1<
@@ -434,6 +441,38 @@ mod m16 {
434441
} // I83
435442
}
436443

444+
mod m17 {
445+
trait MyTrait {
446+
fn f(&self); // I1
447+
} // I2
448+
449+
struct S; // I3
450+
451+
#[rustfmt::skip]
452+
impl MyTrait // $ item=I2
453+
for S { // $ item=I3
454+
fn f(&self) {
455+
println!("M17::MyTrait::f");
456+
} // I4
457+
}
458+
459+
#[rustfmt::skip]
460+
fn g<T: // I5
461+
MyTrait // $ item=I2
462+
>(x: T) { // $ item=I5
463+
x.f(); // $ MISSING: item=I1
464+
T::f(&x); // $ item=I1
465+
MyTrait::f(&x); // $ item=I1
466+
} // I6
467+
468+
#[rustfmt::skip]
469+
pub fn f() {
470+
g( // $ item=I6
471+
S // $ item=I3
472+
);
473+
} // I99
474+
}
475+
437476
fn main() {
438477
my::nested::nested1::nested2::f(); // $ item=I4
439478
my::f(); // $ item=I38
@@ -455,4 +494,5 @@ fn main() {
455494
m11::f(); // $ item=I63
456495
m15::f(); // $ item=I75
457496
m16::f(); // $ item=I83
497+
m17::f(); // $ item=I99
458498
}

0 commit comments

Comments
 (0)