diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 5342bf335da6..070a7d4c6cc2 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -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 @@ -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 @@ -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) + ) + } AstNode getNodeAt(AccessPosition apos) { result = this.getFieldExpr(apos.asFieldPos()).getExpr() @@ -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::Variant { ... }`. - apos.isStructPos() and - result = this.getPath().(TypeMention).resolveTypeAt(path) } Declaration getTarget() { result = resolvePath(this.getPath()) } diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 6ce7a32184cb..21fabe3716ad 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -34,7 +34,7 @@ mod field_access { fn generic_field_access() { // Explicit type argument - let x = GenericThing:: { a: S }; // $ type=x:A.S + let x = GenericThing:: { a: S }; // $ certainType=x:A.S println!("{:?}", x.a); // $ fieldof=GenericThing // Implicit type argument @@ -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, @@ -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:: // $ type=x10:T5.S2 + let x10 = S5:: // $ certainType=x10:T5.S2 { field: Default::default(), // $ target=default }; @@ -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 diff --git a/rust/ql/test/library-tests/type-inference/pattern_matching.rs b/rust/ql/test/library-tests/type-inference/pattern_matching.rs index 9e40560f18c8..569b06ab9a7e 100755 --- a/rust/ql/test/library-tests/type-inference/pattern_matching.rs +++ b/rust/ql/test/library-tests/type-inference/pattern_matching.rs @@ -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 } => { diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index e18a354569fb..4de63e1ff452 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -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 | | 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 | @@ -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 | @@ -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 | & | @@ -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] |