Skip to content

Commit 9e0304b

Browse files
committed
Rust: Type inference for ? expressions
1 parent 0548af3 commit 9e0304b

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

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

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import Type
66
private import Type as T
77
private import TypeMention
88
private import codeql.typeinference.internal.TypeInference
9+
private import codeql.rust.frameworks.stdlib.Stdlib
910

1011
class Type = T::Type;
1112

@@ -891,6 +892,17 @@ private Type inferRefExprType(Expr e, TypePath path) {
891892
)
892893
}
893894

895+
pragma[nomagic]
896+
private Type inferTryExprType(TryExpr te, TypePath path) {
897+
exists(TypeParam tp |
898+
result = inferType(te.getExpr(), TypePath::cons(TTypeParamTypeParameter(tp), path))
899+
|
900+
tp = any(ResultEnum r).getGenericParamList().getGenericParam(0)
901+
or
902+
tp = any(OptionEnum o).getGenericParamList().getGenericParam(0)
903+
)
904+
}
905+
894906
cached
895907
private module Cached {
896908
private import codeql.rust.internal.CachedStages
@@ -1008,6 +1020,8 @@ private module Cached {
10081020
result = inferFieldExprType(n, path)
10091021
or
10101022
result = inferRefExprType(n, path)
1023+
or
1024+
result = inferTryExprType(n, path)
10111025
}
10121026
}
10131027

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -930,22 +930,22 @@ mod try_expressions {
930930

931931
// Simple function using ? operator with same error types
932932
fn try_same_error() -> Result<S1, S1> {
933-
let x = Result::Ok(S1)?; // $ MISSING: type=x:S1
933+
let x = Result::Ok(S1)?; // $ type=x:S1
934934
Result::Ok(S1)
935935
}
936936

937937
// Function using ? operator with different error types that need conversion
938938
fn try_convert_error() -> Result<S1, S2> {
939939
let x = Result::Ok(S1);
940-
let y = x?; // $ MISSING: type=y:S1
940+
let y = x?; // $ type=y:S1
941941
Result::Ok(S1)
942942
}
943943

944944
// Chained ? operations
945945
fn try_chained() -> Result<S1, S2> {
946946
let x = Result::Ok(Result::Ok(S1));
947947
// First ? returns Result<S1, S2>, second ? returns S1
948-
let y = x?.map(|s| s)?; // $ MISSING: method=map
948+
let y = x?.map(|s| s)?; // $ method=map
949949
Result::Ok(S1)
950950
}
951951

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

+11
Original file line numberDiff line numberDiff line change
@@ -1008,8 +1008,10 @@ inferType
10081008
| main.rs:932:43:935:5 | { ... } | | file://:0:0:0:0 | Result |
10091009
| main.rs:932:43:935:5 | { ... } | E | main.rs:925:5:926:14 | S1 |
10101010
| main.rs:932:43:935:5 | { ... } | T | main.rs:925:5:926:14 | S1 |
1011+
| main.rs:933:13:933:13 | x | | main.rs:925:5:926:14 | S1 |
10111012
| main.rs:933:17:933:30 | ...::Ok(...) | | file://:0:0:0:0 | Result |
10121013
| main.rs:933:17:933:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
1014+
| main.rs:933:17:933:31 | TryExpr | | main.rs:925:5:926:14 | S1 |
10131015
| main.rs:933:28:933:29 | S1 | | main.rs:925:5:926:14 | S1 |
10141016
| main.rs:934:9:934:22 | ...::Ok(...) | | file://:0:0:0:0 | Result |
10151017
| main.rs:934:9:934:22 | ...::Ok(...) | E | main.rs:925:5:926:14 | S1 |
@@ -1023,8 +1025,10 @@ inferType
10231025
| main.rs:939:17:939:30 | ...::Ok(...) | | file://:0:0:0:0 | Result |
10241026
| main.rs:939:17:939:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
10251027
| main.rs:939:28:939:29 | S1 | | main.rs:925:5:926:14 | S1 |
1028+
| main.rs:940:13:940:13 | y | | main.rs:925:5:926:14 | S1 |
10261029
| main.rs:940:17:940:17 | x | | file://:0:0:0:0 | Result |
10271030
| main.rs:940:17:940:17 | x | T | main.rs:925:5:926:14 | S1 |
1031+
| main.rs:940:17:940:18 | TryExpr | | main.rs:925:5:926:14 | S1 |
10281032
| main.rs:941:9:941:22 | ...::Ok(...) | | file://:0:0:0:0 | Result |
10291033
| main.rs:941:9:941:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 |
10301034
| main.rs:941:9:941:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
@@ -1044,6 +1048,9 @@ inferType
10441048
| main.rs:948:17:948:17 | x | | file://:0:0:0:0 | Result |
10451049
| main.rs:948:17:948:17 | x | T | file://:0:0:0:0 | Result |
10461050
| main.rs:948:17:948:17 | x | T.T | main.rs:925:5:926:14 | S1 |
1051+
| main.rs:948:17:948:18 | TryExpr | | file://:0:0:0:0 | Result |
1052+
| main.rs:948:17:948:18 | TryExpr | T | main.rs:925:5:926:14 | S1 |
1053+
| main.rs:948:17:948:29 | ... .map(...) | | file://:0:0:0:0 | Result |
10471054
| main.rs:949:9:949:22 | ...::Ok(...) | | file://:0:0:0:0 | Result |
10481055
| main.rs:949:9:949:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 |
10491056
| main.rs:949:9:949:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
@@ -1054,11 +1061,15 @@ inferType
10541061
| main.rs:953:69:960:5 | { ... } | | file://:0:0:0:0 | Result |
10551062
| main.rs:953:69:960:5 | { ... } | E | main.rs:925:5:926:14 | S1 |
10561063
| main.rs:953:69:960:5 | { ... } | T | main.rs:953:20:953:27 | T |
1064+
| main.rs:954:13:954:17 | value | | main.rs:953:20:953:27 | T |
10571065
| main.rs:954:21:954:25 | input | | file://:0:0:0:0 | Result |
10581066
| main.rs:954:21:954:25 | input | E | main.rs:925:5:926:14 | S1 |
10591067
| main.rs:954:21:954:25 | input | T | main.rs:953:20:953:27 | T |
1068+
| main.rs:954:21:954:26 | TryExpr | | main.rs:953:20:953:27 | T |
10601069
| main.rs:955:22:955:38 | ...::Ok(...) | | file://:0:0:0:0 | Result |
1070+
| main.rs:955:22:955:38 | ...::Ok(...) | T | main.rs:953:20:953:27 | T |
10611071
| main.rs:955:22:958:10 | ... .and_then(...) | | file://:0:0:0:0 | Result |
1072+
| main.rs:955:33:955:37 | value | | main.rs:953:20:953:27 | T |
10621073
| main.rs:955:53:958:9 | { ... } | | file://:0:0:0:0 | Result |
10631074
| main.rs:955:53:958:9 | { ... } | E | main.rs:925:5:926:14 | S1 |
10641075
| main.rs:957:13:957:34 | ...::Ok::<...>(...) | | file://:0:0:0:0 | Result |

0 commit comments

Comments
 (0)