Skip to content

Commit aa48536

Browse files
committed
Rust: Add Copilot generated test for ? operator expressions
1 parent 6599a2e commit aa48536

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
@@ -946,6 +946,99 @@ mod impl_overlap {
946946
}
947947
}
948948

949+
mod try_expressions {
950+
use std::fmt::Debug;
951+
952+
#[derive(Debug)]
953+
struct S1;
954+
955+
#[derive(Debug)]
956+
struct S2;
957+
958+
#[derive(Debug)]
959+
enum MyResult<T, E> {
960+
MyOk(T),
961+
MyErr(E),
962+
}
963+
964+
impl<T, E> MyResult<T, E> {
965+
fn map<U, F>(self, op: F) -> MyResult<U, E>
966+
where
967+
F: FnOnce(T) -> U,
968+
{
969+
match self {
970+
MyResult::MyOk(t) => MyResult::MyOk(op(t)),
971+
MyResult::MyErr(e) => MyResult::MyErr(e),
972+
}
973+
}
974+
975+
fn and_then<U, F>(self, op: F) -> MyResult<U, E>
976+
where
977+
F: FnOnce(T) -> MyResult<U, E>,
978+
{
979+
match self {
980+
MyResult::MyOk(t) => op(t),
981+
MyResult::MyErr(e) => MyResult::MyErr(e),
982+
}
983+
}
984+
}
985+
986+
// For the try operator to work, we need to implement From<E> for OtherE
987+
impl From<S1> for S2 {
988+
fn from(s: S1) -> S2 {
989+
S2
990+
}
991+
}
992+
993+
// Simple function using ? operator with same error types
994+
fn try_same_error() -> MyResult<S1, S1> {
995+
let x = MyResult::MyOk(S1)?; // $ type=x:S1
996+
MyResult::MyOk(x)
997+
}
998+
999+
// Function using ? operator with different error types that need conversion
1000+
fn try_convert_error() -> MyResult<S1, S2> {
1001+
let x: MyResult<S1, S1> = MyResult::MyOk(S1);
1002+
let y = x?; // $ type=y:S1
1003+
MyResult::MyOk(y)
1004+
}
1005+
1006+
// Chained ? operations
1007+
fn try_chained() -> MyResult<S1, S2> {
1008+
let x: MyResult<MyResult<S1, S1>, S1> = MyResult::MyOk(MyResult::MyOk(S1));
1009+
let y = x?.map(|s| s)?; // First ? returns MyResult<S1, S1>, second ? returns S1
1010+
MyResult::MyOk(y)
1011+
}
1012+
1013+
// Function that uses ? with closures and complex error cases
1014+
fn try_complex<T: Debug>(input: MyResult<T, S1>) -> MyResult<T, S2> {
1015+
let value = input?; // $ method=From::from
1016+
let mapped = MyResult::MyOk(value).and_then(|v| {
1017+
println!("{:?}", v);
1018+
MyResult::MyOk::<_, S1>(v)
1019+
})?; // $ method=From::from
1020+
MyResult::MyOk(mapped)
1021+
}
1022+
1023+
pub fn f() {
1024+
if let MyResult::MyOk(result) = try_same_error() {
1025+
println!("{:?}", result);
1026+
}
1027+
1028+
if let MyResult::MyOk(result) = try_convert_error() {
1029+
println!("{:?}", result);
1030+
}
1031+
1032+
if let MyResult::MyOk(result) = try_chained() {
1033+
println!("{:?}", result);
1034+
}
1035+
1036+
if let MyResult::MyOk(result) = try_complex(MyResult::MyOk(S1)) {
1037+
println!("{:?}", result);
1038+
}
1039+
}
1040+
}
1041+
9491042
fn main() {
9501043
field_access::f();
9511044
method_impl::f();
@@ -963,4 +1056,5 @@ fn main() {
9631056
implicit_self_borrow::f();
9641057
borrowed_typed::f();
9651058
impl_overlap::f();
1059+
try_expressions::f();
9661060
}

0 commit comments

Comments
 (0)