Skip to content

Commit ff4cb51

Browse files
committed
Rust: Improve handling of where clauses in type inference and path resolution
1 parent 5e5b630 commit ff4cb51

File tree

8 files changed

+93
-25
lines changed

8 files changed

+93
-25
lines changed

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,36 @@ module Impl {
3636
not this.hasGenericParamList() and
3737
result = 0
3838
}
39+
40+
private int nrOfDirectTypeBounds() {
41+
result = this.getTypeBoundList().getNumberOfBounds()
42+
or
43+
not this.hasTypeBoundList() and
44+
result = 0
45+
}
46+
47+
/**
48+
* Gets the `index`th type bound of this trait, if any.
49+
*
50+
* This includes type bounds directly on the trait and bounds from any
51+
* `where` clauses for `Self`.
52+
*/
53+
TypeBound getTypeBound(int index) {
54+
result = this.getTypeBoundList().getBound(index)
55+
or
56+
exists(WherePred wp |
57+
wp = this.getWhereClause().getAPredicate() and
58+
wp.getTypeRepr().(PathTypeRepr).getPath().getText() = "Self" and
59+
result = wp.getTypeBoundList().getBound(index - this.nrOfDirectTypeBounds())
60+
)
61+
}
62+
63+
/**
64+
* Gets a type bound of this trait.
65+
*
66+
* This includes type bounds directly on the trait and bounds from any
67+
* `where` clauses for `Self`.
68+
*/
69+
TypeBound getATypeBound() { result = this.getTypeBound(_) }
3970
}
4071
}

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

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

1617
// the following QLdoc is generated: if you need to edit it, do it in the schema file
1718
/**
@@ -27,6 +28,36 @@ module Impl {
2728
/** Gets the position of this type parameter. */
2829
int getPosition() { this = any(GenericParamList l).getTypeParam(result) }
2930

31+
private int nrOfDirectTypeBounds() {
32+
result = this.getTypeBoundList().getNumberOfBounds()
33+
or
34+
not this.hasTypeBoundList() and
35+
result = 0
36+
}
37+
38+
/**
39+
* Gets the `index`th type bound of this type parameter, if any.
40+
*
41+
* This includes type bounds directly on this type parameter and bounds from
42+
* any `where` clauses for this type parameter.
43+
*/
44+
TypeBound getTypeBound(int index) {
45+
exists(TypeBoundList tbl, int offset | result = tbl.getBound(index - offset) |
46+
tbl = this.getTypeBoundList() and offset = 0
47+
or
48+
tbl = this.(TypeParamItemNode).getAWherePred().getTypeBoundList() and
49+
offset = this.nrOfDirectTypeBounds()
50+
)
51+
}
52+
53+
/**
54+
* Gets a type bound of this type parameter.
55+
*
56+
* This includes type bounds directly on this type parameter and bounds from
57+
* any `where` clauses for this type parameter.
58+
*/
59+
TypeBound getATypeBound() { result = this.getTypeBound(_) }
60+
3061
override string toAbbreviatedString() { result = this.getName().getText() }
3162

3263
override string toStringImpl() { result = this.getName().getText() }

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

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -791,9 +791,7 @@ private class StructItemNode extends TypeItemNode instanceof Struct {
791791

792792
class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait {
793793
pragma[nomagic]
794-
Path getABoundPath() {
795-
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
796-
}
794+
Path getABoundPath() { result = super.getATypeBound().getTypeRepr().(PathTypeRepr).getPath() }
797795

798796
pragma[nomagic]
799797
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
@@ -924,7 +922,8 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
924922
}
925923

926924
class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
927-
private WherePred getAWherePred() {
925+
/** Gets a where predicate for this type parameter, if any */
926+
WherePred getAWherePred() {
928927
exists(ItemNode declaringItem |
929928
this = resolveTypeParamPathTypeRepr(result.getTypeRepr()) and
930929
result = declaringItem.getADescendant() and
@@ -933,14 +932,12 @@ class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
933932
}
934933

935934
pragma[nomagic]
936-
Path getABoundPath() {
937-
exists(TypeBoundList tbl | result = tbl.getABound().getTypeRepr().(PathTypeRepr).getPath() |
938-
tbl = super.getTypeBoundList()
939-
or
940-
tbl = this.getAWherePred().getTypeBoundList()
941-
)
935+
Path getTypeBoundPath(int index) {
936+
result = super.getTypeBound(index).getTypeRepr().(PathTypeRepr).getPath()
942937
}
943938

939+
Path getABoundPath() { result = this.getTypeBoundPath(_) }
940+
944941
pragma[nomagic]
945942
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
946943

@@ -956,12 +953,7 @@ class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
956953
* ```
957954
*/
958955
cached
959-
predicate hasTraitBound() {
960-
Stages::PathResolutionStage::ref() and
961-
exists(this.getABoundPath())
962-
or
963-
exists(this.getAWherePred())
964-
}
956+
predicate hasTraitBound() { Stages::PathResolutionStage::ref() and exists(this.getABoundPath()) }
965957

966958
/**
967959
* Holds if this type parameter has no trait bound. Examples:

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private module Input2 implements InputSig2 {
147147
TypeMention getABaseTypeMention(Type t) { none() }
148148

149149
TypeMention getATypeParameterConstraint(TypeParameter tp) {
150-
result = tp.(TypeParamTypeParameter).getTypeParam().getTypeBoundList().getABound().getTypeRepr()
150+
result = tp.(TypeParamTypeParameter).getTypeParam().getATypeBound().getTypeRepr()
151151
or
152152
result = tp.(SelfTypeParameter).getTrait()
153153
or
@@ -180,12 +180,12 @@ private module Input2 implements InputSig2 {
180180
exists(Trait trait |
181181
abs = trait and
182182
condition = trait and
183-
constraint = trait.getTypeBoundList().getABound().getTypeRepr()
183+
constraint = trait.getATypeBound().getTypeRepr()
184184
)
185185
or
186186
// trait bounds on type parameters
187187
exists(TypeParam param |
188-
abs = param.getTypeBoundList().getABound() and
188+
abs = param.getATypeBound() and
189189
condition = param and
190190
constraint = abs.(TypeBound).getTypeRepr()
191191
)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,9 @@ mod m15 {
321321
TT: Trait1, // $ item=ITT item=I79
322322
{
323323
fn f(&self, tt: TT) { // $ item=ITT
324-
Self::g(self); // $ MISSING: item=I80
324+
Self::g(self); // $ item=I80
325325
TT::g(&tt); // $ item=I80
326-
self.g(); // $ MISSING: item=I80
326+
self.g(); // $ item=I80
327327
}
328328
} // ITrait3
329329

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ resolvePath
162162
| main.rs:321:13:321:18 | Trait1 | main.rs:299:5:303:5 | trait Trait1 |
163163
| main.rs:323:25:323:26 | TT | main.rs:317:9:317:10 | TT |
164164
| main.rs:324:13:324:16 | Self | main.rs:315:5:328:5 | trait Trait3 |
165+
| main.rs:324:13:324:19 | ...::g | main.rs:302:9:302:20 | fn g |
165166
| main.rs:325:13:325:14 | TT | main.rs:317:9:317:10 | TT |
166167
| main.rs:325:13:325:17 | ...::g | main.rs:302:9:302:20 | fn g |
167168
| main.rs:333:10:333:15 | Trait1 | main.rs:299:5:303:5 | trait Trait1 |

rust/ql/test/library-tests/type-inference/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ mod type_parameter_bounds {
550550
T: FirstTrait<S1>,
551551
{
552552
let s = x.method(); // $ target=FirstTrait::method
553-
println!("{:?}", s); // $ MISSING: type=s:S1
553+
println!("{:?}", s); // $ type=s:S1
554554
}
555555

556556
trait Pair<P1 = bool, P2 = i64> {
@@ -830,8 +830,8 @@ mod associated_type_in_supertrait {
830830
{
831831
// Subtrait2::insert_two
832832
fn insert_two(&self, c1: Self::Content, c2: Self::Content) {
833-
self.insert(c1); // $ MISSING: target=Supertrait::insert
834-
self.insert(c2); // $ MISSING: target=Supertrait::insert
833+
self.insert(c1); // $ target=Supertrait::insert
834+
self.insert(c2); // $ target=Supertrait::insert
835835
}
836836
}
837837

@@ -856,7 +856,7 @@ mod associated_type_in_supertrait {
856856
}
857857

858858
fn insert_three<T: Subtrait2>(item: &T, c1: T::Content, c2: T::Content, c3: T::Content) {
859-
item.insert(c1); // $ MISSING: target=Supertrait::insert
859+
item.insert(c1); // $ target=Supertrait::insert
860860
item.insert_two(c2, c3); // $ target=Subtrait2::insert_two
861861
}
862862

rust/ql/test/library-tests/type-inference/type-inference.expected

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,11 +1340,14 @@ inferType
13401340
| main.rs:545:18:545:26 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
13411341
| main.rs:545:26:545:26 | s | | main.rs:508:5:509:14 | S1 |
13421342
| main.rs:548:43:548:43 | x | | main.rs:548:40:548:40 | T |
1343+
| main.rs:552:13:552:13 | s | | main.rs:508:5:509:14 | S1 |
13431344
| main.rs:552:17:552:17 | x | | main.rs:548:40:548:40 | T |
1345+
| main.rs:552:17:552:26 | x.method() | | main.rs:508:5:509:14 | S1 |
13441346
| main.rs:553:18:553:23 | "{:?}\\n" | | file://:0:0:0:0 | & |
13451347
| main.rs:553:18:553:23 | "{:?}\\n" | &T | {EXTERNAL LOCATION} | str |
13461348
| main.rs:553:18:553:26 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
13471349
| main.rs:553:18:553:26 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
1350+
| main.rs:553:26:553:26 | s | | main.rs:508:5:509:14 | S1 |
13481351
| main.rs:557:16:557:19 | SelfParam | | main.rs:556:5:560:5 | Self [trait Pair] |
13491352
| main.rs:559:16:559:19 | SelfParam | | main.rs:556:5:560:5 | Self [trait Pair] |
13501353
| main.rs:562:58:562:58 | x | | main.rs:562:41:562:55 | T |
@@ -1683,10 +1686,14 @@ inferType
16831686
| main.rs:823:24:823:28 | SelfParam | &T | main.rs:821:5:824:5 | Self [trait Subtrait] |
16841687
| main.rs:832:23:832:27 | SelfParam | | file://:0:0:0:0 | & |
16851688
| main.rs:832:23:832:27 | SelfParam | &T | main.rs:826:5:836:5 | Self [trait Subtrait2] |
1689+
| main.rs:832:30:832:31 | c1 | | main.rs:816:9:816:21 | Content |
1690+
| main.rs:832:49:832:50 | c2 | | main.rs:816:9:816:21 | Content |
16861691
| main.rs:833:13:833:16 | self | | file://:0:0:0:0 | & |
16871692
| main.rs:833:13:833:16 | self | &T | main.rs:826:5:836:5 | Self [trait Subtrait2] |
1693+
| main.rs:833:25:833:26 | c1 | | main.rs:816:9:816:21 | Content |
16881694
| main.rs:834:13:834:16 | self | | file://:0:0:0:0 | & |
16891695
| main.rs:834:13:834:16 | self | &T | main.rs:826:5:836:5 | Self [trait Subtrait2] |
1696+
| main.rs:834:25:834:26 | c2 | | main.rs:816:9:816:21 | Content |
16901697
| main.rs:842:19:842:23 | SelfParam | | file://:0:0:0:0 | & |
16911698
| main.rs:842:19:842:23 | SelfParam | &T | main.rs:838:5:838:24 | MyType |
16921699
| main.rs:842:19:842:23 | SelfParam | &T.T | main.rs:840:10:840:10 | T |
@@ -1716,10 +1723,16 @@ inferType
17161723
| main.rs:855:9:855:26 | item.get_content() | | main.rs:816:9:816:21 | Content |
17171724
| main.rs:858:35:858:38 | item | | file://:0:0:0:0 | & |
17181725
| main.rs:858:35:858:38 | item | &T | main.rs:858:21:858:32 | T |
1726+
| main.rs:858:45:858:46 | c1 | | main.rs:816:9:816:21 | Content |
1727+
| main.rs:858:61:858:62 | c2 | | main.rs:816:9:816:21 | Content |
1728+
| main.rs:858:77:858:78 | c3 | | main.rs:816:9:816:21 | Content |
17191729
| main.rs:859:9:859:12 | item | | file://:0:0:0:0 | & |
17201730
| main.rs:859:9:859:12 | item | &T | main.rs:858:21:858:32 | T |
1731+
| main.rs:859:21:859:22 | c1 | | main.rs:816:9:816:21 | Content |
17211732
| main.rs:860:9:860:12 | item | | file://:0:0:0:0 | & |
17221733
| main.rs:860:9:860:12 | item | &T | main.rs:858:21:858:32 | T |
1734+
| main.rs:860:25:860:26 | c2 | | main.rs:816:9:816:21 | Content |
1735+
| main.rs:860:29:860:30 | c3 | | main.rs:816:9:816:21 | Content |
17231736
| main.rs:864:13:864:17 | item1 | | main.rs:838:5:838:24 | MyType |
17241737
| main.rs:864:13:864:17 | item1 | T | {EXTERNAL LOCATION} | i64 |
17251738
| main.rs:864:21:864:33 | MyType(...) | | main.rs:838:5:838:24 | MyType |

0 commit comments

Comments
 (0)