Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions rust/ql/lib/codeql/rust/internal/TypeInference.qll
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,14 @@ module CertainTypeInference {
)
}

private Type inferCertainStructExprType(StructExpr se, TypePath path) {
result = se.getPath().(TypeMention).resolveTypeAt(path)
}

private Type inferCertainStructPatType(StructPat sp, TypePath path) {
result = sp.getPath().(TypeMention).resolveTypeAt(path)
}

predicate certainTypeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
prefix1.isEmpty() and
prefix2.isEmpty() and
Expand Down Expand Up @@ -440,6 +448,10 @@ module CertainTypeInference {
or
result = inferLogicalOperationType(n, path)
or
result = inferCertainStructExprType(n, path)
or
result = inferCertainStructPatType(n, path)
or
result = inferRangeExprType(n) and
path.isEmpty()
or
Expand Down Expand Up @@ -743,7 +755,12 @@ private module StructExprMatchingInput implements MatchingInputSig {
class AccessPosition = DeclarationPosition;

class Access extends StructExpr {
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
exists(TypePath suffix |
suffix.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path) and
result = CertainTypeInference::inferCertainType(this, suffix)
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing this should prune some predicates thanks to the not exists(getTypeArgument(a, target, tp, _)) checks in the shared library. Using inferCertainType will include both explicit types in the path to the struct as well as other certain ways to infer the type parameter.

}

AstNode getNodeAt(AccessPosition apos) {
result = this.getFieldExpr(apos.asFieldPos()).getExpr()
Expand All @@ -754,11 +771,6 @@ private module StructExprMatchingInput implements MatchingInputSig {

Type getInferredType(AccessPosition apos, TypePath path) {
result = inferType(this.getNodeAt(apos), path)
or
// The struct/enum type is supplied explicitly as a type qualifier, e.g.
// `Foo<Bar>::Variant { ... }`.
apos.isStructPos() and
result = this.getPath().(TypeMention).resolveTypeAt(path)
}

Declaration getTarget() { result = resolvePath(this.getPath()) }
Expand Down
8 changes: 4 additions & 4 deletions rust/ql/test/library-tests/type-inference/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ mod field_access {

fn generic_field_access() {
// Explicit type argument
let x = GenericThing::<S> { a: S }; // $ type=x:A.S
let x = GenericThing::<S> { a: S }; // $ certainType=x:A.S
println!("{:?}", x.a); // $ fieldof=GenericThing

// Implicit type argument
Expand Down Expand Up @@ -2384,7 +2384,7 @@ mod loops {
let range_full = ..; // $ certainType=range_full:RangeFull
for i in &[1i64, 2i64, 3i64][range_full] {} // $ target=index MISSING: type=i:&T.i64

let range1 = // $ type=range1:Range type=range1:Idx.u16
let range1 = // $ certainType=range1:Range type=range1:Idx.u16
std::ops::Range {
start: 0u16,
end: 10u16,
Expand Down Expand Up @@ -2480,7 +2480,7 @@ mod explicit_type_args {
let x7 = S4(S2); // $ type=x7:T4.S2
let x8 = S4(0); // $ type=x8:T4.i32
let x9 = S4(S2::default()); // $ type=x9:T4.S2 target=default
let x10 = S5::<S2> // $ type=x10:T5.S2
let x10 = S5::<S2> // $ certainType=x10:T5.S2
{
field: Default::default(), // $ target=default
};
Expand Down Expand Up @@ -2594,7 +2594,7 @@ pub mod exec {
impl Connection for MySqlConnection {}

pub fn f() {
let c = MySqlConnection {}; // $ type=c:MySqlConnection
let c = MySqlConnection {}; // $ certainType=c:MySqlConnection

c.execute1(); // $ MISSING: target=execute1
MySqlConnection::execute1(&c); // $ MISSING: target=execute1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,16 +360,16 @@ pub fn record_patterns() {
// RecordPat - Record (struct) patterns
match point {
Point { x: 0, y: 0 } => {
let origin = point; // $ type=origin:Point
let origin = point; // $ certainType=origin:Point
println!("Origin point: {:?}", origin);
}
Point { x, y: 0 } => {
let x_axis_x = x; // $ type=x_axis_x:i32
let x_axis_point = point; // $ type=x_axis_point:Point
let x_axis_point = point; // $ certainType=x_axis_point:Point
println!("Point on x-axis: x={}, point={:?}", x_axis_x, x_axis_point);
}
Point { x: 10, .. } => {
let ten_x_point = point; // $ type=ten_x_point:Point
let ten_x_point = point; // $ certainType=ten_x_point:Point
println!("Point with x=10: {:?}", ten_x_point);
}
Point { x, y } => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,6 @@ inferType
| dereference.rs:122:23:122:29 | &... | &T | file://:0:0:0:0 | & |
| dereference.rs:122:23:122:29 | &... | &T.&T | dereference.rs:99:5:100:21 | Key |
| dereference.rs:122:24:122:29 | Key {...} | | dereference.rs:99:5:100:21 | Key |
| dereference.rs:122:24:122:29 | Key {...} | | file://:0:0:0:0 | & |
| dereference.rs:122:24:122:29 | Key {...} | &T | dereference.rs:99:5:100:21 | Key |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These and the removed types below are spurious, so this is an improvement.

| dereference.rs:123:16:123:28 | Some(...) | | {EXTERNAL LOCATION} | Option |
| dereference.rs:123:16:123:28 | Some(...) | T | file://:0:0:0:0 | & |
| dereference.rs:123:16:123:28 | Some(...) | T.&T | dereference.rs:99:5:100:21 | Key |
Expand Down Expand Up @@ -501,10 +499,8 @@ inferType
| dyn_type.rs:61:5:61:36 | ...::new(...) | T | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:61:5:61:36 | ...::new(...) | T.A | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:5:61:36 | ...::new(...) | T.dyn(A) | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | | dyn_type.rs:10:1:13:1 | dyn GenericGet |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | A | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:14:61:35 | GenStruct {...} | dyn(A) | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:61:33:61:33 | a | | dyn_type.rs:60:18:60:43 | A |
| dyn_type.rs:64:25:64:27 | obj | | file://:0:0:0:0 | & |
| dyn_type.rs:64:25:64:27 | obj | &T | dyn_type.rs:5:1:8:1 | dyn MyTrait1 |
Expand Down Expand Up @@ -623,16 +619,13 @@ inferType
| dyn_type.rs:102:26:102:48 | &... | | file://:0:0:0:0 | & |
| dyn_type.rs:102:26:102:48 | &... | &T | dyn_type.rs:5:1:8:1 | dyn MyTrait1 |
| dyn_type.rs:102:26:102:48 | &... | &T | dyn_type.rs:21:1:24:1 | MyStruct |
| dyn_type.rs:102:27:102:48 | MyStruct {...} | | dyn_type.rs:5:1:8:1 | dyn MyTrait1 |
| dyn_type.rs:102:27:102:48 | MyStruct {...} | | dyn_type.rs:21:1:24:1 | MyStruct |
| dyn_type.rs:102:45:102:46 | 42 | | {EXTERNAL LOCATION} | i32 |
| dyn_type.rs:103:28:105:5 | &... | | file://:0:0:0:0 | & |
| dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:10:1:13:1 | dyn GenericGet |
| dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:103:28:105:5 | &... | &T.dyn(A) | {EXTERNAL LOCATION} | String |
| dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:10:1:13:1 | dyn GenericGet |
| dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:103:29:105:5 | GenStruct {...} | dyn(A) | {EXTERNAL LOCATION} | String |
| dyn_type.rs:104:16:104:17 | "" | | file://:0:0:0:0 | & |
| dyn_type.rs:104:16:104:17 | "" | &T | {EXTERNAL LOCATION} | str |
| dyn_type.rs:107:21:107:45 | &... | | file://:0:0:0:0 | & |
Expand All @@ -641,11 +634,8 @@ inferType
| dyn_type.rs:107:21:107:45 | &... | &T.A | {EXTERNAL LOCATION} | i32 |
| dyn_type.rs:107:21:107:45 | &... | &T.dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:107:21:107:45 | &... | &T.dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | | dyn_type.rs:15:1:19:1 | dyn AssocTrait |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | A | {EXTERNAL LOCATION} | i32 |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | dyn(AP) | {EXTERNAL LOCATION} | bool |
| dyn_type.rs:107:22:107:45 | GenStruct {...} | dyn(GP) | {EXTERNAL LOCATION} | i64 |
| dyn_type.rs:107:41:107:43 | 100 | | {EXTERNAL LOCATION} | i32 |
| loop/main.rs:7:12:7:15 | SelfParam | | loop/main.rs:6:1:8:1 | Self [trait T1] |
| loop/main.rs:11:12:11:15 | SelfParam | | loop/main.rs:10:1:14:1 | Self [trait T2] |
Expand Down