Skip to content

Commit aa97bf9

Browse files
committed
Rust: Add type inference tests
1 parent 179bae8 commit aa97bf9

File tree

2 files changed

+878
-696
lines changed

2 files changed

+878
-696
lines changed

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

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,68 @@ mod method_non_parametric_trait_impl {
191191
}
192192
}
193193

194+
mod type_parameter_bounds {
195+
use std::fmt::Debug;
196+
197+
#[derive(Debug)]
198+
struct S1;
199+
200+
#[derive(Debug)]
201+
struct S2;
202+
203+
// Two traits with the same method name.
204+
205+
trait FirstTrait<FT> {
206+
fn method(self) -> FT;
207+
}
208+
209+
trait SecondTrait<ST> {
210+
fn method(self) -> ST;
211+
}
212+
213+
fn call_first_trait_per_bound<I: Debug, T: SecondTrait<I>>(x: T) {
214+
// The type parameter bound determines which method this call is resolved to.
215+
let s1 = x.method(); // missing type for `s1`
216+
println!("{:?}", s1);
217+
}
218+
219+
fn call_second_trait_per_bound<I: Debug, T: SecondTrait<I>>(x: T) {
220+
// The type parameter bound determines which method this call is resolved to.
221+
let s2 = x.method(); // missing type for `s2`
222+
println!("{:?}", s2);
223+
}
224+
225+
fn trait_bound_with_type<T: FirstTrait<S1>>(x: T) {
226+
let s = x.method(); // missing type for `s`
227+
println!("{:?}", s);
228+
}
229+
230+
fn trait_per_bound_with_type<T: FirstTrait<S1>>(x: T) {
231+
let s = x.method(); // missing type for `s`
232+
println!("{:?}", s);
233+
}
234+
235+
trait Pair<P1, P2> {
236+
fn fst(self) -> P1;
237+
238+
fn snd(self) -> P2;
239+
}
240+
241+
fn call_trait_per_bound_with_type_1<T: Pair<S1, S2>>(x: T, y: T) {
242+
// The type in the type parameter bound determines the return type.
243+
let s1 = x.fst(); // missing type for `s1`
244+
let s2 = y.snd(); // missing type for `s2`
245+
println!("{:?}, {:?}", s1, s2);
246+
}
247+
248+
fn call_trait_per_bound_with_type_2<T2: Debug, T: Pair<S1, T2>>(x: T, y: T) {
249+
// The type in the type parameter bound determines the return type.
250+
let s1 = x.fst(); // missing type for `s1`
251+
let s2 = y.snd(); // missing type for `s2`
252+
println!("{:?}, {:?}", s1, s2);
253+
}
254+
}
255+
194256
mod function_trait_bounds {
195257
#[derive(Debug)]
196258
struct MyThing<A> {
@@ -443,6 +505,49 @@ mod function_trait_bounds_2 {
443505
}
444506
}
445507

508+
mod type_aliases {
509+
#[derive(Debug)]
510+
enum PairOption<Fst, Snd> {
511+
PairNone(),
512+
PairFst(Fst),
513+
PairSnd(Snd),
514+
PairBoth(Fst, Snd),
515+
}
516+
517+
#[derive(Debug)]
518+
struct S1;
519+
520+
#[derive(Debug)]
521+
struct S2;
522+
523+
#[derive(Debug)]
524+
struct S3;
525+
526+
// Non-generic type alias that fully applies the generic type
527+
type MyPair = PairOption<S1, S2>;
528+
529+
// Generic type alias that partially applies the generic type
530+
type AnotherPair<Thr> = PairOption<S2, Thr>;
531+
532+
pub fn f() {
533+
// Type can be infered from the constructor
534+
let p1: MyPair = PairOption::PairBoth(S1, S2);
535+
println!("{:?}", p1);
536+
537+
// Type can be only infered from the type alias
538+
let p2: MyPair = PairOption::PairNone(); // types for `Fst` and `Snd` missing
539+
println!("{:?}", p2);
540+
541+
// First type from alias, second from constructor
542+
let p3: AnotherPair<_> = PairOption::PairSnd(S3); // type for `Fst` missing
543+
println!("{:?}", p3);
544+
545+
// First type from alias definition, second from argument to alias
546+
let p3: AnotherPair<S3> = PairOption::PairNone(); // type for `Snd` missing, spurious `S3` for `Fst`
547+
println!("{:?}", p3);
548+
}
549+
}
550+
446551
mod option_methods {
447552
#[derive(Debug)]
448553
enum MyOption<T> {

0 commit comments

Comments
 (0)