mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Merge pull request #19367 from hvitved/rust/type-inference-try-expr
Rust: Type inference for `?` expressions
This commit is contained in:
@@ -6,6 +6,7 @@ private import Type
|
||||
private import Type as T
|
||||
private import TypeMention
|
||||
private import codeql.typeinference.internal.TypeInference
|
||||
private import codeql.rust.frameworks.stdlib.Stdlib
|
||||
|
||||
class Type = T::Type;
|
||||
|
||||
@@ -873,6 +874,17 @@ private Type inferRefExprType(Expr e, TypePath path) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferTryExprType(TryExpr te, TypePath path) {
|
||||
exists(TypeParam tp |
|
||||
result = inferType(te.getExpr(), TypePath::cons(TTypeParamTypeParameter(tp), path))
|
||||
|
|
||||
tp = any(ResultEnum r).getGenericParamList().getGenericParam(0)
|
||||
or
|
||||
tp = any(OptionEnum o).getGenericParamList().getGenericParam(0)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
private import codeql.rust.internal.CachedStages
|
||||
@@ -1012,6 +1024,8 @@ private module Cached {
|
||||
result = inferFieldExprType(n, path)
|
||||
or
|
||||
result = inferRefExprType(n, path)
|
||||
or
|
||||
result = inferTryExprType(n, path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
multipleMethodCallTargets
|
||||
| main.rs:11:5:18:5 | conn.execute(...) | file://:0:0:0:0 | fn execute |
|
||||
| main.rs:11:5:18:5 | conn.execute(...) | file://:0:0:0:0 | fn execute |
|
||||
| main.rs:22:5:22:37 | conn.execute(...) | file://:0:0:0:0 | fn execute |
|
||||
| main.rs:22:5:22:37 | conn.execute(...) | file://:0:0:0:0 | fn execute |
|
||||
| main.rs:23:5:23:38 | conn.batch_execute(...) | file://:0:0:0:0 | fn batch_execute |
|
||||
| main.rs:23:5:23:38 | conn.batch_execute(...) | file://:0:0:0:0 | fn batch_execute |
|
||||
| main.rs:25:5:25:32 | conn.prepare(...) | file://:0:0:0:0 | fn prepare |
|
||||
| main.rs:25:5:25:32 | conn.prepare(...) | file://:0:0:0:0 | fn prepare |
|
||||
| main.rs:28:5:28:35 | conn.query(...) | file://:0:0:0:0 | fn query |
|
||||
| main.rs:28:5:28:35 | conn.query(...) | file://:0:0:0:0 | fn query |
|
||||
| main.rs:29:5:29:39 | conn.query_one(...) | file://:0:0:0:0 | fn query_one |
|
||||
| main.rs:29:5:29:39 | conn.query_one(...) | file://:0:0:0:0 | fn query_one |
|
||||
| main.rs:30:5:30:39 | conn.query_opt(...) | file://:0:0:0:0 | fn query_opt |
|
||||
| main.rs:30:5:30:39 | conn.query_opt(...) | file://:0:0:0:0 | fn query_opt |
|
||||
| main.rs:35:17:35:67 | conn.query(...) | file://:0:0:0:0 | fn query |
|
||||
| main.rs:35:17:35:67 | conn.query(...) | file://:0:0:0:0 | fn query |
|
||||
@@ -919,6 +919,65 @@ mod borrowed_typed {
|
||||
}
|
||||
}
|
||||
|
||||
mod try_expressions {
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct S1;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct S2;
|
||||
|
||||
// Simple function using ? operator with same error types
|
||||
fn try_same_error() -> Result<S1, S1> {
|
||||
let x = Result::Ok(S1)?; // $ type=x:S1
|
||||
Result::Ok(S1)
|
||||
}
|
||||
|
||||
// Function using ? operator with different error types that need conversion
|
||||
fn try_convert_error() -> Result<S1, S2> {
|
||||
let x = Result::Ok(S1);
|
||||
let y = x?; // $ type=y:S1
|
||||
Result::Ok(S1)
|
||||
}
|
||||
|
||||
// Chained ? operations
|
||||
fn try_chained() -> Result<S1, S2> {
|
||||
let x = Result::Ok(Result::Ok(S1));
|
||||
// First ? returns Result<S1, S2>, second ? returns S1
|
||||
let y = x?.map(|s| s)?; // $ method=map
|
||||
Result::Ok(S1)
|
||||
}
|
||||
|
||||
// Function that uses ? with closures and complex error cases
|
||||
fn try_complex<T: Debug>(input: Result<T, S1>) -> Result<T, S1> {
|
||||
let value = input?;
|
||||
let mapped = Result::Ok(value).and_then(|v| {
|
||||
println!("{:?}", v);
|
||||
Result::Ok::<_, S1>(v)
|
||||
})?; // $ method=and_then
|
||||
Result::Err(S1)
|
||||
}
|
||||
|
||||
pub fn f() {
|
||||
if let Result::Ok(result) = try_same_error() {
|
||||
println!("{:?}", result);
|
||||
}
|
||||
|
||||
if let Result::Ok(result) = try_convert_error() {
|
||||
println!("{:?}", result);
|
||||
}
|
||||
|
||||
if let Result::Ok(result) = try_chained() {
|
||||
println!("{:?}", result);
|
||||
}
|
||||
|
||||
if let Result::Ok(result) = try_complex(Result::Ok(S1)) {
|
||||
println!("{:?}", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
field_access::f();
|
||||
method_impl::f();
|
||||
@@ -935,4 +994,5 @@ fn main() {
|
||||
trait_implicit_self_borrow::f();
|
||||
implicit_self_borrow::f();
|
||||
borrowed_typed::f();
|
||||
try_expressions::f();
|
||||
}
|
||||
|
||||
@@ -1005,7 +1005,96 @@ inferType
|
||||
| main.rs:918:15:918:16 | &x | | file://:0:0:0:0 | & |
|
||||
| main.rs:918:15:918:16 | &x | &T | main.rs:894:5:894:13 | S |
|
||||
| main.rs:918:16:918:16 | x | | main.rs:894:5:894:13 | S |
|
||||
| main.rs:924:5:924:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:925:5:925:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:925:20:925:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:925:41:925:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:932:43:935:5 | { ... } | | file://:0:0:0:0 | Result |
|
||||
| main.rs:932:43:935:5 | { ... } | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:932:43:935:5 | { ... } | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:933:13:933:13 | x | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:933:17:933:30 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:933:17:933:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:933:17:933:31 | TryExpr | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:933:28:933:29 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:934:9:934:22 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:934:9:934:22 | ...::Ok(...) | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:934:9:934:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:934:20:934:21 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:938:46:942:5 | { ... } | | file://:0:0:0:0 | Result |
|
||||
| main.rs:938:46:942:5 | { ... } | E | main.rs:928:5:929:14 | S2 |
|
||||
| main.rs:938:46:942:5 | { ... } | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:939:13:939:13 | x | | file://:0:0:0:0 | Result |
|
||||
| main.rs:939:13:939:13 | x | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:939:17:939:30 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:939:17:939:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:939:28:939:29 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:940:13:940:13 | y | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:940:17:940:17 | x | | file://:0:0:0:0 | Result |
|
||||
| main.rs:940:17:940:17 | x | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:940:17:940:18 | TryExpr | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:941:9:941:22 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:941:9:941:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 |
|
||||
| main.rs:941:9:941:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:941:20:941:21 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:945:40:950:5 | { ... } | | file://:0:0:0:0 | Result |
|
||||
| main.rs:945:40:950:5 | { ... } | E | main.rs:928:5:929:14 | S2 |
|
||||
| main.rs:945:40:950:5 | { ... } | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:946:13:946:13 | x | | file://:0:0:0:0 | Result |
|
||||
| main.rs:946:13:946:13 | x | T | file://:0:0:0:0 | Result |
|
||||
| main.rs:946:13:946:13 | x | T.T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:946:17:946:42 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:946:17:946:42 | ...::Ok(...) | T | file://:0:0:0:0 | Result |
|
||||
| main.rs:946:17:946:42 | ...::Ok(...) | T.T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:946:28:946:41 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:946:28:946:41 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:946:39:946:40 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:948:17:948:17 | x | | file://:0:0:0:0 | Result |
|
||||
| main.rs:948:17:948:17 | x | T | file://:0:0:0:0 | Result |
|
||||
| main.rs:948:17:948:17 | x | T.T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:948:17:948:18 | TryExpr | | file://:0:0:0:0 | Result |
|
||||
| main.rs:948:17:948:18 | TryExpr | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:948:17:948:29 | ... .map(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:949:9:949:22 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:949:9:949:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 |
|
||||
| main.rs:949:9:949:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:949:20:949:21 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:953:30:953:34 | input | | file://:0:0:0:0 | Result |
|
||||
| main.rs:953:30:953:34 | input | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:953:30:953:34 | input | T | main.rs:953:20:953:27 | T |
|
||||
| main.rs:953:69:960:5 | { ... } | | file://:0:0:0:0 | Result |
|
||||
| main.rs:953:69:960:5 | { ... } | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:953:69:960:5 | { ... } | T | main.rs:953:20:953:27 | T |
|
||||
| main.rs:954:13:954:17 | value | | main.rs:953:20:953:27 | T |
|
||||
| main.rs:954:21:954:25 | input | | file://:0:0:0:0 | Result |
|
||||
| main.rs:954:21:954:25 | input | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:954:21:954:25 | input | T | main.rs:953:20:953:27 | T |
|
||||
| main.rs:954:21:954:26 | TryExpr | | main.rs:953:20:953:27 | T |
|
||||
| main.rs:955:22:955:38 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:955:22:955:38 | ...::Ok(...) | T | main.rs:953:20:953:27 | T |
|
||||
| main.rs:955:22:958:10 | ... .and_then(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:955:33:955:37 | value | | main.rs:953:20:953:27 | T |
|
||||
| main.rs:955:53:958:9 | { ... } | | file://:0:0:0:0 | Result |
|
||||
| main.rs:955:53:958:9 | { ... } | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:957:13:957:34 | ...::Ok::<...>(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:957:13:957:34 | ...::Ok::<...>(...) | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:959:9:959:23 | ...::Err(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:959:9:959:23 | ...::Err(...) | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:959:9:959:23 | ...::Err(...) | T | main.rs:953:20:953:27 | T |
|
||||
| main.rs:959:21:959:22 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:963:37:963:52 | try_same_error(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:963:37:963:52 | try_same_error(...) | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:963:37:963:52 | try_same_error(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:967:37:967:55 | try_convert_error(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:967:37:967:55 | try_convert_error(...) | E | main.rs:928:5:929:14 | S2 |
|
||||
| main.rs:967:37:967:55 | try_convert_error(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:971:37:971:49 | try_chained(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:971:37:971:49 | try_chained(...) | E | main.rs:928:5:929:14 | S2 |
|
||||
| main.rs:971:37:971:49 | try_chained(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:975:37:975:63 | try_complex(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:975:37:975:63 | try_complex(...) | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:975:37:975:63 | try_complex(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:975:49:975:62 | ...::Ok(...) | | file://:0:0:0:0 | Result |
|
||||
| main.rs:975:49:975:62 | ...::Ok(...) | E | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:975:49:975:62 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:975:60:975:61 | S1 | | main.rs:925:5:926:14 | S1 |
|
||||
| main.rs:983:5:983:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:984:5:984:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:984:20:984:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:984:41:984:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
|
||||
|
||||
Reference in New Issue
Block a user