diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 5ebb8eaa3175..9967e21d3ec9 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -250,6 +250,12 @@ private Struct getRangeType(RangeExpr re) { result instanceof RangeToInclusiveStruct } +/** A `let` statement with an annotation without any uses of the `_` type syntax. */ +predicate fullyAnnotatedLetStmt(LetStmt let) { + exists(let.getTypeRepr()) and + not exists(InferTypeRepr t | t.getParentNode*() = let.getTypeRepr()) +} + /** * Holds if the type tree of `n1` at `prefix1` should be equal to the type tree * of `n2` at `prefix2` and type information should propagate in both directions @@ -266,6 +272,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat ) or exists(LetStmt let | + not fullyAnnotatedLetStmt(let) and let.getPat() = n1 and let.getInitializer() = n2 ) @@ -352,15 +359,35 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat ) } +/** + * Similar to `typeEquality` but we only want type information to flow along the + * equality from left to right. That is, the type of `n2` will be inferred from + * the type of `n1`, but not the other way around. + */ +private predicate directionalTypeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) { + prefix1.isEmpty() and + prefix2.isEmpty() and + exists(LetStmt let | + fullyAnnotatedLetStmt(let) and + let.getPat() = n1 and + let.getInitializer() = n2 + ) +} + pragma[nomagic] private Type inferTypeEquality(AstNode n, TypePath path) { exists(TypePath prefix1, AstNode n2, TypePath prefix2, TypePath suffix | result = inferType(n2, prefix2.appendInverse(suffix)) and path = prefix1.append(suffix) | + // use type equality from right to left typeEquality(n, prefix1, n2, prefix2) or + // use type equality from left to right typeEquality(n2, prefix2, n, prefix1) + or + // use type equality from left to right + directionalTypeEquality(n2, prefix2, n, prefix1) ) } 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 e4da3d0dd168..d333cca78198 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -3438,21 +3438,17 @@ inferType | main.rs:2114:15:2114:15 | x | | {EXTERNAL LOCATION} | bool | | main.rs:2114:32:2116:9 | { ... } | | {EXTERNAL LOCATION} | bool | | main.rs:2115:13:2115:13 | x | | {EXTERNAL LOCATION} | bool | -| main.rs:2120:13:2120:13 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2120:13:2120:13 | x | | {EXTERNAL LOCATION} | i64 | | main.rs:2120:22:2120:23 | 73 | | {EXTERNAL LOCATION} | i32 | | main.rs:2120:22:2120:23 | 73 | | {EXTERNAL LOCATION} | i64 | -| main.rs:2121:9:2121:9 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2121:9:2121:9 | x | | {EXTERNAL LOCATION} | i64 | | main.rs:2121:9:2121:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | | main.rs:2121:18:2121:21 | 5i64 | | {EXTERNAL LOCATION} | i64 | -| main.rs:2122:9:2122:9 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2122:9:2122:9 | x | | {EXTERNAL LOCATION} | i64 | | main.rs:2122:9:2122:23 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | | main.rs:2122:18:2122:22 | &5i64 | | file://:0:0:0:0 | & | | main.rs:2122:18:2122:22 | &5i64 | &T | {EXTERNAL LOCATION} | i64 | | main.rs:2122:19:2122:22 | 5i64 | | {EXTERNAL LOCATION} | i64 | -| main.rs:2123:9:2123:9 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2123:9:2123:9 | x | | {EXTERNAL LOCATION} | i64 | | main.rs:2123:9:2123:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | | main.rs:2123:18:2123:21 | true | | {EXTERNAL LOCATION} | bool | @@ -3558,7 +3554,6 @@ inferType | main.rs:2171:18:2171:22 | vals2 | | file://:0:0:0:0 | [] | | main.rs:2171:18:2171:22 | vals2 | [T;...] | {EXTERNAL LOCATION} | u16 | | main.rs:2173:13:2173:17 | vals3 | | file://:0:0:0:0 | [] | -| main.rs:2173:13:2173:17 | vals3 | [T;...] | {EXTERNAL LOCATION} | i32 | | main.rs:2173:13:2173:17 | vals3 | [T;...] | {EXTERNAL LOCATION} | u32 | | main.rs:2173:26:2173:26 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2173:31:2173:39 | [...] | | file://:0:0:0:0 | [] | @@ -3570,13 +3565,10 @@ inferType | main.rs:2173:35:2173:35 | 2 | | {EXTERNAL LOCATION} | u32 | | main.rs:2173:38:2173:38 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2173:38:2173:38 | 3 | | {EXTERNAL LOCATION} | u32 | -| main.rs:2174:13:2174:13 | u | | {EXTERNAL LOCATION} | i32 | | main.rs:2174:13:2174:13 | u | | {EXTERNAL LOCATION} | u32 | | main.rs:2174:18:2174:22 | vals3 | | file://:0:0:0:0 | [] | -| main.rs:2174:18:2174:22 | vals3 | [T;...] | {EXTERNAL LOCATION} | i32 | | main.rs:2174:18:2174:22 | vals3 | [T;...] | {EXTERNAL LOCATION} | u32 | | main.rs:2176:13:2176:17 | vals4 | | file://:0:0:0:0 | [] | -| main.rs:2176:13:2176:17 | vals4 | [T;...] | {EXTERNAL LOCATION} | i32 | | main.rs:2176:13:2176:17 | vals4 | [T;...] | {EXTERNAL LOCATION} | u64 | | main.rs:2176:26:2176:26 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2176:31:2176:36 | [1; 3] | | file://:0:0:0:0 | [] | @@ -3585,10 +3577,8 @@ inferType | main.rs:2176:32:2176:32 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2176:32:2176:32 | 1 | | {EXTERNAL LOCATION} | u64 | | main.rs:2176:35:2176:35 | 3 | | {EXTERNAL LOCATION} | i32 | -| main.rs:2177:13:2177:13 | u | | {EXTERNAL LOCATION} | i32 | | main.rs:2177:13:2177:13 | u | | {EXTERNAL LOCATION} | u64 | | main.rs:2177:18:2177:22 | vals4 | | file://:0:0:0:0 | [] | -| main.rs:2177:18:2177:22 | vals4 | [T;...] | {EXTERNAL LOCATION} | i32 | | main.rs:2177:18:2177:22 | vals4 | [T;...] | {EXTERNAL LOCATION} | u64 | | main.rs:2179:17:2179:24 | strings1 | | file://:0:0:0:0 | [] | | main.rs:2179:17:2179:24 | strings1 | [T;...] | file://:0:0:0:0 | & | @@ -3950,16 +3940,13 @@ inferType | main.rs:2255:30:2255:33 | map1 | V.A | {EXTERNAL LOCATION} | Global | | main.rs:2255:30:2255:33 | map1 | V.T | file://:0:0:0:0 | & | | main.rs:2255:30:2255:33 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | -| main.rs:2259:17:2259:17 | a | | {EXTERNAL LOCATION} | i32 | | main.rs:2259:17:2259:17 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:2259:26:2259:26 | 0 | | {EXTERNAL LOCATION} | i32 | | main.rs:2259:26:2259:26 | 0 | | {EXTERNAL LOCATION} | i64 | -| main.rs:2261:23:2261:23 | a | | {EXTERNAL LOCATION} | i32 | | main.rs:2261:23:2261:23 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:2261:23:2261:28 | ... < ... | | {EXTERNAL LOCATION} | bool | | main.rs:2261:27:2261:28 | 10 | | {EXTERNAL LOCATION} | i32 | | main.rs:2261:27:2261:28 | 10 | | {EXTERNAL LOCATION} | i64 | -| main.rs:2263:13:2263:13 | a | | {EXTERNAL LOCATION} | i32 | | main.rs:2263:13:2263:13 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:2263:13:2263:18 | ... += ... | | file://:0:0:0:0 | () | | main.rs:2263:18:2263:18 | 1 | | {EXTERNAL LOCATION} | i32 | @@ -4953,8 +4940,6 @@ inferType | pattern_matching.rs:504:22:504:71 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | | pattern_matching.rs:510:9:510:13 | slice | | file://:0:0:0:0 | & | | pattern_matching.rs:510:9:510:13 | slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:510:9:510:13 | slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:510:9:510:13 | slice | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:510:9:510:13 | slice | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:510:25:510:40 | &... | | file://:0:0:0:0 | & | | pattern_matching.rs:510:25:510:40 | &... | &T | file://:0:0:0:0 | [] | @@ -4972,23 +4957,15 @@ inferType | pattern_matching.rs:510:39:510:39 | 5 | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:513:11:513:15 | slice | | file://:0:0:0:0 | & | | pattern_matching.rs:513:11:513:15 | slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:513:11:513:15 | slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:513:11:513:15 | slice | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:513:11:513:15 | slice | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:514:9:514:10 | SlicePat | | file://:0:0:0:0 | & | | pattern_matching.rs:514:9:514:10 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:514:9:514:10 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:514:9:514:10 | SlicePat | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:514:9:514:10 | SlicePat | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:515:17:515:27 | empty_slice | | file://:0:0:0:0 | & | | pattern_matching.rs:515:17:515:27 | empty_slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:515:17:515:27 | empty_slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:515:17:515:27 | empty_slice | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:515:17:515:27 | empty_slice | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:515:31:515:35 | slice | | file://:0:0:0:0 | & | | pattern_matching.rs:515:31:515:35 | slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:515:31:515:35 | slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:515:31:515:35 | slice | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:515:31:515:35 | slice | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:516:22:516:40 | "Empty slice: {:?}\\n" | | file://:0:0:0:0 | & | | pattern_matching.rs:516:22:516:40 | "Empty slice: {:?}\\n" | &T | {EXTERNAL LOCATION} | str | @@ -4996,13 +4973,9 @@ inferType | pattern_matching.rs:516:22:516:53 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | | pattern_matching.rs:516:43:516:53 | empty_slice | | file://:0:0:0:0 | & | | pattern_matching.rs:516:43:516:53 | empty_slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:516:43:516:53 | empty_slice | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:516:43:516:53 | empty_slice | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:516:43:516:53 | empty_slice | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:518:9:518:11 | SlicePat | | file://:0:0:0:0 | & | | pattern_matching.rs:518:9:518:11 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:518:9:518:11 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:518:9:518:11 | SlicePat | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:518:9:518:11 | SlicePat | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:520:22:520:41 | "Single element: {}\\n" | | file://:0:0:0:0 | & | | pattern_matching.rs:520:22:520:41 | "Single element: {}\\n" | &T | {EXTERNAL LOCATION} | str | @@ -5010,8 +4983,6 @@ inferType | pattern_matching.rs:520:22:520:54 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | | pattern_matching.rs:522:9:522:23 | SlicePat | | file://:0:0:0:0 | & | | pattern_matching.rs:522:9:522:23 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:522:9:522:23 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:522:9:522:23 | SlicePat | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:522:9:522:23 | SlicePat | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:525:22:525:43 | "Two elements: {}, {}\\n" | | file://:0:0:0:0 | & | | pattern_matching.rs:525:22:525:43 | "Two elements: {}, {}\\n" | &T | {EXTERNAL LOCATION} | str | @@ -5019,8 +4990,6 @@ inferType | pattern_matching.rs:525:22:525:70 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | | pattern_matching.rs:527:9:527:34 | SlicePat | | file://:0:0:0:0 | & | | pattern_matching.rs:527:9:527:34 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:527:9:527:34 | SlicePat | &T | file://:0:0:0:0 | [] | -| pattern_matching.rs:527:9:527:34 | SlicePat | &T.[T;...] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:527:9:527:34 | SlicePat | &T.[T] | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:532:17:532:53 | "First: {}, last: {}, middle l... | | file://:0:0:0:0 | & | | pattern_matching.rs:532:17:532:53 | "First: {}, last: {}, middle l... | &T | {EXTERNAL LOCATION} | str | @@ -5434,3 +5403,4 @@ inferType | pattern_matching.rs:809:9:809:9 | _ | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:814:5:814:7 | f(...) | | {EXTERNAL LOCATION} | Option | testFailures +| main.rs:2263:21:2263:53 | //... | Missing result: target=add_assign |