Skip to content

Commit ffa9bf6

Browse files
committed
Rust: Add Copilot generated test for ? operator expressions
1 parent 389f15e commit ffa9bf6

File tree

1 file changed

+94
-0
lines changed
  • rust/ql/test/library-tests/type-inference

1 file changed

+94
-0
lines changed

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

+94
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,99 @@ mod borrowed_typed {
919919
}
920920
}
921921

922+
mod try_expressions {
923+
use std::fmt::Debug;
924+
925+
#[derive(Debug)]
926+
struct S1;
927+
928+
#[derive(Debug)]
929+
struct S2;
930+
931+
#[derive(Debug)]
932+
enum MyResult<T, E> {
933+
MyOk(T),
934+
MyErr(E),
935+
}
936+
937+
impl<T, E> MyResult<T, E> {
938+
fn map<U, F>(self, op: F) -> MyResult<U, E>
939+
where
940+
F: FnOnce(T) -> U,
941+
{
942+
match self {
943+
MyResult::MyOk(t) => MyResult::MyOk(op(t)),
944+
MyResult::MyErr(e) => MyResult::MyErr(e),
945+
}
946+
}
947+
948+
fn and_then<U, F>(self, op: F) -> MyResult<U, E>
949+
where
950+
F: FnOnce(T) -> MyResult<U, E>,
951+
{
952+
match self {
953+
MyResult::MyOk(t) => op(t),
954+
MyResult::MyErr(e) => MyResult::MyErr(e),
955+
}
956+
}
957+
}
958+
959+
// For the try operator to work, we need to implement From<E> for OtherE
960+
impl From<S1> for S2 {
961+
fn from(s: S1) -> S2 {
962+
S2
963+
}
964+
}
965+
966+
// Simple function using ? operator with same error types
967+
fn try_same_error() -> MyResult<S1, S1> {
968+
let x = MyResult::MyOk(S1)?; // $ type=x:S1
969+
MyResult::MyOk(x)
970+
}
971+
972+
// Function using ? operator with different error types that need conversion
973+
fn try_convert_error() -> MyResult<S1, S2> {
974+
let x: MyResult<S1, S1> = MyResult::MyOk(S1);
975+
let y = x?; // $ type=y:S1
976+
MyResult::MyOk(y)
977+
}
978+
979+
// Chained ? operations
980+
fn try_chained() -> MyResult<S1, S2> {
981+
let x: MyResult<MyResult<S1, S1>, S1> = MyResult::MyOk(MyResult::MyOk(S1));
982+
let y = x?.map(|s| s)?; // First ? returns MyResult<S1, S1>, second ? returns S1
983+
MyResult::MyOk(y)
984+
}
985+
986+
// Function that uses ? with closures and complex error cases
987+
fn try_complex<T: Debug>(input: MyResult<T, S1>) -> MyResult<T, S2> {
988+
let value = input?; // $ method=From::from
989+
let mapped = MyResult::MyOk(value).and_then(|v| {
990+
println!("{:?}", v);
991+
MyResult::MyOk::<_, S1>(v)
992+
})?; // $ method=From::from
993+
MyResult::MyOk(mapped)
994+
}
995+
996+
pub fn f() {
997+
if let MyResult::MyOk(result) = try_same_error() {
998+
println!("{:?}", result);
999+
}
1000+
1001+
if let MyResult::MyOk(result) = try_convert_error() {
1002+
println!("{:?}", result);
1003+
}
1004+
1005+
if let MyResult::MyOk(result) = try_chained() {
1006+
println!("{:?}", result);
1007+
}
1008+
1009+
if let MyResult::MyOk(result) = try_complex(MyResult::MyOk(S1)) {
1010+
println!("{:?}", result);
1011+
}
1012+
}
1013+
}
1014+
9221015
fn main() {
9231016
field_access::f();
9241017
method_impl::f();
@@ -935,4 +1028,5 @@ fn main() {
9351028
trait_implicit_self_borrow::f();
9361029
implicit_self_borrow::f();
9371030
borrowed_typed::f();
1031+
try_expressions::f();
9381032
}

0 commit comments

Comments
 (0)