Skip to content

Rust: add more type inference tests for patterns and a simple one for a closure call #20029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 29 additions & 127 deletions rust/ql/test/library-tests/type-inference/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![feature(box_patterns)]
mod field_access {
#[derive(Debug)]
struct S;

#[derive(Debug)]
struct MyThing {
a: S,
Expand Down Expand Up @@ -2351,139 +2351,39 @@ mod tuples {
}
}

pub mod pattern_matching {
struct MyRecordStruct<T1, T2> {
value1: T1,
value2: T2,
}

struct MyTupleStruct<T1, T2>(T1, T2);

enum MyEnum<T1, T2> {
Variant1 { value1: T1, value2: T2 },
Variant2(T2, T1),
}
pub mod pattern_matching;
pub mod pattern_matching_experimental {
pub fn box_patterns() {
let boxed_value = Box::new(100i32); // $ method=new

pub fn f() -> Option<()> {
let value = Some(42);
if let Some(mesg) = value {
let mesg = mesg; // $ type=mesg:i32
println!("{mesg}");
}
match value {
Some(mesg) => {
let mesg = mesg; // $ type=mesg:i32
println!("{mesg}");
// BoxPat - Box patterns (requires feature flag)
match boxed_value {
box 100 => {
println!("Boxed 100");
}
None => (),
};
let mesg = value.unwrap(); // $ method=unwrap
let mesg = mesg; // $ type=mesg:i32
println!("{mesg}");
let mesg = value?; // $ type=mesg:i32
println!("{mesg}");

let value2 = &Some(42);
if let &Some(mesg) = value2 {
let mesg = mesg; // $ type=mesg:i32
println!("{mesg}");
}

let value3 = 42;
if let ref mesg = value3 {
let mesg = mesg; // $ type=mesg:&T.i32
println!("{mesg}");
}

let value4 = Some(42);
if let Some(ref mesg) = value4 {
let mesg = mesg; // $ type=mesg:&T.i32
println!("{mesg}");
}

let ref value5 = 42;
let x = value5; // $ type=x:&T.i32

let my_record_struct = MyRecordStruct {
value1: 42,
value2: false,
};
if let MyRecordStruct { value1, value2 } = my_record_struct {
let x = value1; // $ type=x:i32
let y = value2; // $ type=y:bool
();
}

let my_tuple_struct = MyTupleStruct(42, false);
if let MyTupleStruct(value1, value2) = my_tuple_struct {
let x = value1; // $ type=x:i32
let y = value2; // $ type=y:bool
();
}

let my_enum1 = MyEnum::Variant1 {
value1: 42,
value2: false,
};
match my_enum1 {
MyEnum::Variant1 { value1, value2 } => {
let x = value1; // $ type=x:i32
let y = value2; // $ type=y:bool
();
}
MyEnum::Variant2(value1, value2) => {
let x = value1; // $ type=x:bool
let y = value2; // $ type=y:i32
();
box x => {
let unboxed = x; // $ MISSING: type=unboxed:i32
println!("Boxed value: {}", unboxed);
}
}

let my_nested_enum = MyEnum::Variant2(
false,
MyRecordStruct {
value1: 42,
value2: "string",
},
);

match my_nested_enum {
MyEnum::Variant2(
value1,
MyRecordStruct {
value1: x,
value2: y,
},
) => {
let a = value1; // $ type=a:bool
let b = x; // $ type=b:i32
let c = y; // $ type=c:&T.str
();
// Nested box pattern
let nested_box = Box::new(Box::new(42i32)); // $ method=new
match nested_box {
box box x => {
let nested_unboxed = x; // $ MISSING: type=nested_unboxed:i32
println!("Nested boxed: {}", nested_unboxed);
}
_ => (),
}
}
}

let opt1 = Some(Default::default()); // $ type=opt1:T.i32 method=default
#[rustfmt::skip]
let _ = if let Some::<i32>(x) = opt1
{
x; // $ type=x:i32
};

let opt2 = Some(Default::default()); // $ type=opt2:T.i32 method=default
#[rustfmt::skip]
let _ = if let Option::Some::<i32>(x) = opt2
{
x; // $ type=x:i32
};

let opt3 = Some(Default::default()); // $ type=opt3:T.i32 method=default
#[rustfmt::skip]
let _ = if let Option::<i32>::Some(x) = opt3
{
x; // $ type=x:i32
};

None
mod closures {
pub fn f() {
Some(1).map(|x| {
let x = x; // $ MISSING: type=x:i32
println!("{x}");
}); // $ method=map
}
}

Expand Down Expand Up @@ -2515,5 +2415,7 @@ fn main() {
method_determined_by_argument_type::f(); // $ method=f
tuples::f(); // $ method=f
dereference::test(); // $ method=test
pattern_matching::f(); // $ method=f
pattern_matching::test_all_patterns(); // $ method=test_all_patterns
pattern_matching_experimental::box_patterns(); // $ method=box_patterns
closures::f() // $ method=f
}
1 change: 1 addition & 0 deletions rust/ql/test/library-tests/type-inference/options.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
qltest_use_nightly: true
Loading