Skip to content

Commit c22021a

Browse files
authored
Merge pull request #18808 from hvitved/rust/path-resolution-inherited-functions
Rust: Path resolution for inherited associated items
2 parents 485ee5c + 54ebe9a commit c22021a

File tree

5 files changed

+298
-50
lines changed

5 files changed

+298
-50
lines changed

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ abstract class ItemNode extends AstNode {
130130
call = this.getASuccessorRec(_) and
131131
result = call.(ItemNode).getASuccessorRec(name)
132132
)
133+
or
134+
// a trait has access to the associated items of its supertraits
135+
result = this.(TraitItemNode).resolveABound().getASuccessorRec(name) and
136+
result instanceof AssocItemNode
137+
or
138+
// items made available by an implementation where `this` is the implementing type
139+
exists(ItemNode node |
140+
this = node.(ImplItemNode).resolveSelfTy() and
141+
result = node.getASuccessorRec(name) and
142+
result instanceof AssocItemNode
143+
)
133144
}
134145

135146
/** Gets a successor named `name` of this item, if any. */
@@ -179,7 +190,10 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
179190
override Visibility getVisibility() { none() }
180191
}
181192

182-
private class ConstItemNode extends ItemNode instanceof Const {
193+
/** An item that can occur in a trait or an `impl` block. */
194+
abstract private class AssocItemNode extends ItemNode { }
195+
196+
private class ConstItemNode extends AssocItemNode instanceof Const {
183197
override string getName() { result = Const.super.getName().getText() }
184198

185199
override Namespace getNamespace() { result.isValue() }
@@ -205,7 +219,7 @@ private class VariantItemNode extends ItemNode instanceof Variant {
205219
override Visibility getVisibility() { result = Variant.super.getVisibility() }
206220
}
207221

208-
private class FunctionItemNode extends ItemNode instanceof Function {
222+
private class FunctionItemNode extends AssocItemNode instanceof Function {
209223
override string getName() { result = Function.super.getName().getText() }
210224

211225
override Namespace getNamespace() { result.isValue() }
@@ -239,7 +253,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
239253
override Visibility getVisibility() { result = Impl.super.getVisibility() }
240254
}
241255

242-
private class MacroCallItemNode extends ItemNode instanceof MacroCall {
256+
private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
243257
override string getName() { result = "(macro call)" }
244258

245259
override Namespace getNamespace() { none() }
@@ -269,14 +283,21 @@ private class StructItemNode extends ItemNode instanceof Struct {
269283
}
270284

271285
class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
286+
pragma[nomagic]
287+
Path getABoundPath() {
288+
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
289+
}
290+
291+
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
292+
272293
override string getName() { result = Trait.super.getName().getText() }
273294

274295
override Namespace getNamespace() { result.isType() }
275296

276297
override Visibility getVisibility() { result = Trait.super.getVisibility() }
277298
}
278299

279-
class TypeAliasItemNode extends ItemNode instanceof TypeAlias {
300+
class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
280301
override string getName() { result = TypeAlias.super.getName().getText() }
281302

282303
override Namespace getNamespace() { result.isType() }

rust/ql/test/library-tests/dataflow/global/inline-flow.expected

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ edges
4242
| main.rs:103:13:103:30 | mn.data_through(...) | main.rs:103:9:103:9 | b | provenance | |
4343
| main.rs:103:29:103:29 | a | main.rs:79:28:79:33 | ...: i64 | provenance | |
4444
| main.rs:103:29:103:29 | a | main.rs:103:13:103:30 | mn.data_through(...) | provenance | |
45+
| main.rs:109:9:109:9 | a | main.rs:110:26:110:26 | a | provenance | |
46+
| main.rs:109:13:109:21 | source(...) | main.rs:109:9:109:9 | a | provenance | |
47+
| main.rs:110:26:110:26 | a | main.rs:67:23:67:28 | ...: i64 | provenance | |
48+
| main.rs:115:9:115:9 | a | main.rs:116:39:116:39 | a | provenance | |
49+
| main.rs:115:13:115:22 | source(...) | main.rs:115:9:115:9 | a | provenance | |
50+
| main.rs:116:9:116:9 | b | main.rs:117:10:117:10 | b | provenance | |
51+
| main.rs:116:13:116:40 | ...::data_through(...) | main.rs:116:9:116:9 | b | provenance | |
52+
| main.rs:116:39:116:39 | a | main.rs:79:28:79:33 | ...: i64 | provenance | |
53+
| main.rs:116:39:116:39 | a | main.rs:116:13:116:40 | ...::data_through(...) | provenance | |
4554
| main.rs:128:12:128:17 | ...: i64 | main.rs:129:24:129:24 | n | provenance | |
4655
| main.rs:129:9:129:26 | MyInt {...} [MyInt] | main.rs:128:28:130:5 | { ... } [MyInt] | provenance | |
4756
| main.rs:129:24:129:24 | n | main.rs:129:9:129:26 | MyInt {...} [MyInt] | provenance | |
@@ -130,6 +139,15 @@ nodes
130139
| main.rs:103:13:103:30 | mn.data_through(...) | semmle.label | mn.data_through(...) |
131140
| main.rs:103:29:103:29 | a | semmle.label | a |
132141
| main.rs:104:10:104:10 | b | semmle.label | b |
142+
| main.rs:109:9:109:9 | a | semmle.label | a |
143+
| main.rs:109:13:109:21 | source(...) | semmle.label | source(...) |
144+
| main.rs:110:26:110:26 | a | semmle.label | a |
145+
| main.rs:115:9:115:9 | a | semmle.label | a |
146+
| main.rs:115:13:115:22 | source(...) | semmle.label | source(...) |
147+
| main.rs:116:9:116:9 | b | semmle.label | b |
148+
| main.rs:116:13:116:40 | ...::data_through(...) | semmle.label | ...::data_through(...) |
149+
| main.rs:116:39:116:39 | a | semmle.label | a |
150+
| main.rs:117:10:117:10 | b | semmle.label | b |
133151
| main.rs:128:12:128:17 | ...: i64 | semmle.label | ...: i64 |
134152
| main.rs:128:28:130:5 | { ... } [MyInt] | semmle.label | { ... } [MyInt] |
135153
| main.rs:129:9:129:26 | MyInt {...} [MyInt] | semmle.label | MyInt {...} [MyInt] |
@@ -179,6 +197,7 @@ subpaths
179197
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:41:13:44:6 | pass_through(...) |
180198
| main.rs:55:26:55:26 | a | main.rs:51:21:51:26 | ...: i64 | main.rs:51:36:53:5 | { ... } | main.rs:55:13:55:27 | pass_through(...) |
181199
| main.rs:103:29:103:29 | a | main.rs:79:28:79:33 | ...: i64 | main.rs:79:43:85:5 | { ... } | main.rs:103:13:103:30 | mn.data_through(...) |
200+
| main.rs:116:39:116:39 | a | main.rs:79:28:79:33 | ...: i64 | main.rs:79:43:85:5 | { ... } | main.rs:116:13:116:40 | ...::data_through(...) |
182201
| main.rs:134:24:134:33 | source(...) | main.rs:128:12:128:17 | ...: i64 | main.rs:128:28:130:5 | { ... } [MyInt] | main.rs:134:13:134:34 | ...::new(...) [MyInt] |
183202
| main.rs:187:49:187:49 | a [MyInt] | main.rs:175:18:175:21 | SelfParam [MyInt] | main.rs:175:48:177:5 | { ... } [MyInt] | main.rs:187:30:187:53 | ...::take_self(...) [MyInt] |
184203
| main.rs:192:54:192:54 | b [MyInt] | main.rs:179:26:179:37 | ...: MyInt [MyInt] | main.rs:179:49:181:5 | { ... } [MyInt] | main.rs:192:30:192:55 | ...::take_second(...) [MyInt] |
@@ -191,8 +210,10 @@ testFailures
191210
| main.rs:45:10:45:10 | a | main.rs:43:9:43:18 | source(...) | main.rs:45:10:45:10 | a | $@ | main.rs:43:9:43:18 | source(...) | source(...) |
192211
| main.rs:56:10:56:10 | b | main.rs:49:13:49:22 | source(...) | main.rs:56:10:56:10 | b | $@ | main.rs:49:13:49:22 | source(...) | source(...) |
193212
| main.rs:68:14:68:14 | n | main.rs:96:13:96:21 | source(...) | main.rs:68:14:68:14 | n | $@ | main.rs:96:13:96:21 | source(...) | source(...) |
213+
| main.rs:68:14:68:14 | n | main.rs:109:13:109:21 | source(...) | main.rs:68:14:68:14 | n | $@ | main.rs:109:13:109:21 | source(...) | source(...) |
194214
| main.rs:91:10:91:10 | a | main.rs:75:13:75:21 | source(...) | main.rs:91:10:91:10 | a | $@ | main.rs:75:13:75:21 | source(...) | source(...) |
195215
| main.rs:104:10:104:10 | b | main.rs:102:13:102:21 | source(...) | main.rs:104:10:104:10 | b | $@ | main.rs:102:13:102:21 | source(...) | source(...) |
216+
| main.rs:117:10:117:10 | b | main.rs:115:13:115:22 | source(...) | main.rs:117:10:117:10 | b | $@ | main.rs:115:13:115:22 | source(...) | source(...) |
196217
| main.rs:136:10:136:10 | m | main.rs:134:24:134:33 | source(...) | main.rs:136:10:136:10 | m | $@ | main.rs:134:24:134:33 | source(...) | source(...) |
197218
| main.rs:188:10:188:10 | c | main.rs:185:28:185:36 | source(...) | main.rs:188:10:188:10 | c | $@ | main.rs:185:28:185:36 | source(...) | source(...) |
198219
| main.rs:193:10:193:10 | c | main.rs:191:28:191:37 | source(...) | main.rs:193:10:193:10 | c | $@ | main.rs:191:28:191:37 | source(...) | source(...) |

rust/ql/test/library-tests/dataflow/global/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ struct MyFlag {
6565

6666
impl MyFlag {
6767
fn data_in(&self, n: i64) {
68-
sink(n); // $ hasValueFlow=1 MISSING: hasValueFlow=8
68+
sink(n); // $ hasValueFlow=1 hasValueFlow=8
6969
}
7070

7171
fn get_data(&self) -> i64 {
@@ -114,7 +114,7 @@ fn data_through_method_called_as_function() {
114114
let mn = MyFlag { flag: true };
115115
let a = source(12);
116116
let b = MyFlag::data_through(&mn, a);
117-
sink(b); // $ MISSING: hasValueFlow=12
117+
sink(b); // $ hasValueFlow=12
118118
}
119119

120120
use std::ops::Add;

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

Lines changed: 147 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ mod m8 {
178178
pub fn g() {
179179
let x = MyStruct {}; // $ item=I50
180180
MyTrait::f(&x); // $ item=I48
181-
MyStruct::f(&x); // $ MISSING: item=I53
181+
MyStruct::f(&x); // $ item=I53
182182
<MyStruct as // $ item=I50
183183
MyTrait // $ MISSING: item=I47
184184
> // $ MISSING: item=52
@@ -187,7 +187,7 @@ mod m8 {
187187
x.f(); // $ MISSING: item=I53
188188
let x = MyStruct {}; // $ item=I50
189189
x.g(); // $ MISSING: item=I54
190-
MyStruct::h(&x); // $ MISSING: item=I74
190+
MyStruct::h(&x); // $ item=I74
191191
x.h(); // $ MISSING: item=I74
192192
} // I55
193193
} // I46
@@ -291,6 +291,149 @@ mod m13 {
291291
}
292292
}
293293

294+
mod m15 {
295+
trait Trait1 {
296+
fn f(&self);
297+
298+
fn g(&self); // I80
299+
} // I79
300+
301+
#[rustfmt::skip]
302+
trait Trait2
303+
: Trait1 { // $ item=I79
304+
fn f(&self) {
305+
println!("m15::Trait2::f");
306+
Self::g(self); // $ item=I80
307+
self.g(); // $ MISSING: item=I80
308+
}
309+
} // I82
310+
311+
struct S; // I81
312+
313+
#[rustfmt::skip]
314+
impl Trait1 // $ item=I79
315+
for S { // $ item=I81
316+
fn f(&self) {
317+
println!("m15::<S as Trait1>::f");
318+
Self::g(self); // $ item=I77
319+
self.g(); // $ MISSING: item=I77
320+
} // I76
321+
322+
fn g(&self) {
323+
println!("m15::<S as Trait1>::g");
324+
} // I77
325+
}
326+
327+
#[rustfmt::skip]
328+
impl Trait2 // $ item=I82
329+
for S { // $ item=I81
330+
fn f(&self) {
331+
println!("m15::<S as Trait2>::f");
332+
} // I78
333+
}
334+
335+
#[rustfmt::skip]
336+
pub fn f() {
337+
println!("m15::f");
338+
let x = S; // $ item=I81
339+
<S // $ item=I81
340+
as Trait1 // $ MISSING: item=I79
341+
>::f(&x); // $ MISSING: item=I76
342+
<S // $ item=I81
343+
as Trait2 // MISSING: item=I82
344+
>::f(&x); // $ MISSING: item=I78
345+
S::g(&x); // $ item=I77
346+
x.g(); // $ MISSING: item=I77
347+
} // I75
348+
}
349+
350+
mod m16 {
351+
#[rustfmt::skip]
352+
trait Trait1<
353+
T // I84
354+
> {
355+
fn f(&self) -> T; // $ item=I84
356+
357+
fn g(&self) -> T // $ item=I84
358+
; // I85
359+
360+
const c: T // $ item=I84
361+
; // I94
362+
} // I86
363+
364+
#[rustfmt::skip]
365+
trait Trait2<
366+
T // I87
367+
> // I88
368+
: Trait1<
369+
T // $ item=I87
370+
> { // $ item=I86
371+
fn f(&self) -> T { // $ item=I87
372+
println!("m16::Trait2::f");
373+
Self::g(self); // $ item=I85
374+
self.g(); // $ MISSING: item=I85
375+
Self::c // $ item=I94
376+
}
377+
} // I89
378+
379+
struct S; // I90
380+
381+
#[rustfmt::skip]
382+
impl Trait1<
383+
S // $ item=I90
384+
> // $ item=I86
385+
for S { // $ item=I90
386+
fn f(&self) -> S { // $ item=I90
387+
println!("m16::<S as Trait1<S>>::f");
388+
Self::g(self); // $ item=I92
389+
self.g() // $ MISSING: item=I92
390+
} // I91
391+
392+
fn g(&self) -> S { // $ item=I90
393+
println!("m16::<S as Trait1<S>>::g");
394+
Self::c // $ item=I95
395+
} // I92
396+
397+
const c: S = S // $ item=I90
398+
; // I95
399+
}
400+
401+
#[rustfmt::skip]
402+
impl Trait2<
403+
S // $ item=I90
404+
> // $ item=I89
405+
for S { // $ item=I90
406+
fn f(&self) -> S { // $ item=I90
407+
println!("m16::<S as Trait2<S>>::f");
408+
Self::c // $ MISSING: item=I95
409+
} // I93
410+
}
411+
412+
#[rustfmt::skip]
413+
pub fn f() {
414+
println!("m16::f");
415+
let x = S; // $ item=I90
416+
<S // $ item=I90
417+
as Trait1<
418+
S // $ item=I90
419+
> // $ MISSING: item=I86
420+
>::f(&x); // $ MISSING: item=I91
421+
<S // $ item=I90
422+
as Trait2<
423+
S // $ item=I90
424+
> // MISSING: item=I89
425+
>::f(&x); // $ MISSING: item=I93
426+
S::g(&x); // $ item=I92
427+
x.g(); // $ MISSING: item=I92
428+
S::c; // $ item=I95
429+
<S // $ item=I90
430+
as Trait1<
431+
S // $ item=I90
432+
> // $ MISSING: item=I86
433+
>::c; // $ MISSING: item=I95
434+
} // I83
435+
}
436+
294437
fn main() {
295438
my::nested::nested1::nested2::f(); // $ item=I4
296439
my::f(); // $ item=I38
@@ -310,4 +453,6 @@ fn main() {
310453
m8::g(); // $ item=I55
311454
m9::f(); // $ item=I57
312455
m11::f(); // $ item=I63
456+
m15::f(); // $ item=I75
457+
m16::f(); // $ item=I83
313458
}

0 commit comments

Comments
 (0)