Skip to content

Commit e6385ac

Browse files
committed
Rust: More type inference tests
1 parent 2015125 commit e6385ac

File tree

3 files changed

+515
-84
lines changed

3 files changed

+515
-84
lines changed

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

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,90 @@ mod dyn_fn_once {
152152
let _r2 = apply_boxed(Box::new(|_: i64| true), 3); // $ target=apply_boxed target=new type=_r2:bool
153153
}
154154
}
155+
156+
mod closure_infer_param {
157+
fn apply1<F: Fn(i64) -> i64>(f: F, a: i64) -> i64 {
158+
f(a)
159+
}
160+
161+
fn apply2(f: impl Fn(i64) -> i64, a: i64) -> i64 {
162+
f(a)
163+
}
164+
165+
fn apply3(f: &dyn Fn(i64) -> i64, a: i64) -> i64 {
166+
f(a)
167+
}
168+
169+
fn apply4<F: FnMut(i64) -> i64>(mut f: F, a: i64) -> i64 {
170+
f(a)
171+
}
172+
173+
fn apply5(f: &mut dyn FnMut(i64) -> i64, a: i64) -> i64 {
174+
f(a)
175+
}
176+
177+
fn apply6<T>(f: impl Fn(T) -> i64, a: T) -> i64 {
178+
f(a)
179+
}
180+
181+
fn apply7<T, F: FnMut(T) -> i64>(mut f: F, a: T) -> i64 {
182+
f(a)
183+
}
184+
185+
fn test() {
186+
let f = |x| x; // $ MISSING: type=x:i64
187+
let _r = apply1(f, 1i64); // $ target=apply1
188+
189+
let f = |x| x; // $ MISSING: type=x:i64
190+
let _r = apply2(f, 2i64); // $ target=apply2
191+
192+
let f = |x| x; // $ MISSING: type=x:i64
193+
let _r = apply3(&f, 3i64); // $ target=apply3
194+
195+
let f = |x| x; // $ MISSING: type=x:i64
196+
let _r = apply4(f, 4i64); // $ target=apply4
197+
198+
let mut f = |x| x; // $ MISSING: type=x:i64
199+
let _r = apply5(&mut f, 5i64); // $ target=apply5
200+
201+
let f = |x| x; // $ MISSING: type=x:i64
202+
let _r = apply6(f, 6i64); // $ target=apply6
203+
204+
let f = |x| x; // $ MISSING: type=x:i64
205+
let _r = apply7(f, 7i64); // $ target=apply7
206+
}
207+
}
208+
209+
mod implicit_deref {
210+
use std::ops::Deref;
211+
212+
struct S<T>(T);
213+
214+
impl<T> Deref for S<T> {
215+
type Target = dyn Fn(T) -> bool;
216+
217+
fn deref(&self) -> &Self::Target {
218+
&|_| false
219+
}
220+
}
221+
222+
pub fn test() {
223+
let x = 0i64;
224+
let v = Default::default(); // $ MISSING: type=v:i64 target=default
225+
let s = S(v);
226+
let _ret = s(x); // $ MISSING: type=_ret:bool
227+
228+
let x = 0i32;
229+
let v = Default::default(); // $ MISSING: type=v:i32 target=default
230+
let s = S(v);
231+
let s_ref = &s;
232+
let _ret = s_ref(x); // $ MISSING: type=_ret:bool
233+
234+
// The call below is not an implicit deref, instead it will target
235+
// `impl<A, F> FnOnce<A> for &F` from
236+
// https://doc.rust-lang.org/std/ops/trait.FnOnce.html#impl-FnOnce%3CA%3E-for-%26F
237+
// and we currently cannot handle inferring the output type
238+
let c = |x| x; // $ MISSING: type=x:i64
239+
(&c)(x); // $ MISSING: type=_:i64
240+
}
241+
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,6 +2878,30 @@ mod closure;
28782878
mod dereference;
28792879
mod dyn_type;
28802880

2881+
mod arg_trait_bounds {
2882+
struct Gen<T>(T);
2883+
2884+
trait Container<T> {
2885+
fn get_input(&self) -> T;
2886+
}
2887+
2888+
fn my_get<T: Container<i64>>(c: &T) -> bool {
2889+
c.get_input() == 42 // $ target=get_input target=eq
2890+
}
2891+
2892+
impl<GT: Copy> Container<GT> for Gen<GT> {
2893+
fn get_input(&self) -> GT {
2894+
self.0 // $ fieldof=Gen
2895+
}
2896+
}
2897+
2898+
fn test() {
2899+
let v = Default::default(); // $ MISSING: type=v:i64 target=default
2900+
let g = Gen(v);
2901+
let _ = my_get(&g); // $ target=my_get
2902+
}
2903+
}
2904+
28812905
fn main() {
28822906
field_access::f(); // $ target=f
28832907
method_impl::f(); // $ target=f

0 commit comments

Comments
 (0)