Skip to content

Commit e12e904

Browse files
committed
Rust: Add more type inference tests
1 parent a0d2005 commit e12e904

File tree

8 files changed

+4827
-4019
lines changed

8 files changed

+4827
-4019
lines changed
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
multipleCallTargets
2-
| dereference.rs:61:15:61:24 | e1.deref() |
3-
| main.rs:2357:13:2357:31 | ...::from(...) |
4-
| main.rs:2358:13:2358:31 | ...::from(...) |
5-
| main.rs:2359:13:2359:31 | ...::from(...) |
6-
| main.rs:2365:13:2365:31 | ...::from(...) |
7-
| main.rs:2366:13:2366:31 | ...::from(...) |
8-
| main.rs:2367:13:2367:31 | ...::from(...) |
2+
| dereference.rs:69:15:69:24 | e1.deref() |
3+
| dereference.rs:186:17:186:25 | S.bar(...) |
4+
| dereference.rs:187:17:187:29 | S.bar(...) |
5+
| invalid/main.rs:91:17:91:30 | S1.duplicate() |
6+
| main.rs:2437:13:2437:31 | ...::from(...) |
7+
| main.rs:2438:13:2438:31 | ...::from(...) |
8+
| main.rs:2439:13:2439:31 | ...::from(...) |
9+
| main.rs:2445:13:2445:31 | ...::from(...) |
10+
| main.rs:2446:13:2446:31 | ...::from(...) |
11+
| main.rs:2447:13:2447:31 | ...::from(...) |

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

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
// Tests for method resolution targeting blanket trait implementations
22

33
mod basic_blanket_impl {
4+
use std::ops::Deref;
5+
46
#[derive(Debug, Copy, Clone)]
57
struct S1;
68

9+
#[derive(Debug, Copy, Clone)]
10+
struct S2;
11+
12+
impl Deref for S2 {
13+
type Target = S1;
14+
15+
fn deref(&self) -> &Self::Target {
16+
&S1
17+
}
18+
}
19+
720
trait Clone1 {
821
fn clone1(&self) -> Self;
922
}
@@ -21,7 +34,7 @@ mod basic_blanket_impl {
2134
}
2235
}
2336

24-
// Blanket implementation for all types that implement Display and Clone
37+
// Blanket implementation for all types that implement Clone1
2538
impl<T: Clone1> Duplicatable for T {
2639
// Clone1duplicate
2740
fn duplicate(&self) -> Self {
@@ -30,10 +43,58 @@ mod basic_blanket_impl {
3043
}
3144

3245
pub fn test_basic_blanket() {
33-
let x = S1.clone1(); // $ target=S1::clone1
34-
println!("{x:?}");
35-
let y = S1.duplicate(); // $ target=Clone1duplicate
36-
println!("{y:?}");
46+
let x1 = S1.clone1(); // $ target=S1::clone1
47+
println!("{x1:?}");
48+
let x2 = (&S1).clone1(); // $ target=S1::clone1
49+
println!("{x2:?}");
50+
let x3 = S1.duplicate(); // $ target=Clone1duplicate
51+
println!("{x3:?}");
52+
let x4 = (&S1).duplicate(); // $ target=Clone1duplicate
53+
println!("{x4:?}");
54+
let x5 = S1::duplicate(&S1); // $ MISSING: target=Clone1duplicate
55+
println!("{x5:?}");
56+
let x6 = S2.duplicate(); // $ MISSING: target=Clone1duplicate
57+
println!("{x6:?}");
58+
let x7 = (&S2).duplicate(); // $ MISSING: target=Clone1duplicate
59+
println!("{x7:?}");
60+
}
61+
}
62+
63+
mod assoc_blanket_impl {
64+
#[derive(Debug, Copy, Clone)]
65+
struct S1;
66+
67+
trait Trait1 {
68+
fn assoc_func1(x: i64, y: Self) -> Self;
69+
}
70+
71+
trait Trait2 {
72+
fn assoc_func2(x: i64, y: Self) -> Self;
73+
}
74+
75+
impl Trait1 for S1 {
76+
// S1::assoc_func1
77+
fn assoc_func1(x: i64, y: Self) -> Self {
78+
y
79+
}
80+
}
81+
82+
impl<T: Trait1> Trait2 for T {
83+
// Blanket_assoc_func2
84+
fn assoc_func2(x: i64, y: Self) -> Self {
85+
T::assoc_func1(x, y) // $ target=assoc_func1
86+
}
87+
}
88+
89+
pub fn test_assoc_blanket() {
90+
let x1 = S1::assoc_func1(1, S1); // $ target=S1::assoc_func1
91+
println!("{x1:?}");
92+
let x2 = Trait1::assoc_func1(1, S1); // $ target=S1::assoc_func1
93+
println!("{x2:?}");
94+
let x3 = S1::assoc_func2(1, S1); // $ MISSING: target=Blanket_assoc_func2
95+
println!("{x3:?}");
96+
let x4 = Trait2::assoc_func2(1, S1); // $ target=Blanket_assoc_func2
97+
println!("{x4:?}");
3798
}
3899
}
39100

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

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ impl<T> Deref for MySmartPointer<T> {
2727
}
2828
}
2929

30+
struct S<T>(T);
31+
32+
impl<T> S<T> {
33+
fn foo(&self) -> &T {
34+
&self.0 // $ fieldof=S
35+
}
36+
}
37+
3038
fn explicit_monomorphic_dereference() {
3139
// Dereference with method call
3240
let a1 = MyIntPointer { value: 34i64 };
@@ -91,6 +99,9 @@ fn implicit_dereference() {
9199
// Call method on implicitly dereferenced value
92100
let x = MySmartPointer { value: 34i64 };
93101
let _y = x.is_positive(); // $ MISSING: target=is_positive type=_y:bool
102+
103+
let z = MySmartPointer { value: S(0i64) };
104+
let z_ = z.foo(); // $ MISSING: target=foo type=z_:&T.i64
94105
}
95106

96107
mod implicit_deref_coercion_cycle {
@@ -128,11 +139,90 @@ mod implicit_deref_coercion_cycle {
128139
}
129140
}
130141

142+
mod ref_vs_mut_ref {
143+
trait MyTrait1<T> {
144+
fn foo(self) -> T;
145+
}
146+
147+
struct S;
148+
149+
impl MyTrait1<S> for &S {
150+
// MyTrait1::foo1
151+
fn foo(self) -> S {
152+
S
153+
}
154+
}
155+
156+
impl MyTrait1<i64> for &mut S {
157+
// MyTrait1::foo2
158+
fn foo(self) -> i64 {
159+
42
160+
}
161+
}
162+
163+
trait MyTrait2<T1, T2> {
164+
fn bar(self, arg: T1) -> T2;
165+
}
166+
167+
impl MyTrait2<&S, S> for S {
168+
// MyTrait2::bar1
169+
fn bar(self, arg: &S) -> S {
170+
S
171+
}
172+
}
173+
174+
impl MyTrait2<&mut S, i64> for S {
175+
// MyTrait2::bar2
176+
fn bar(self, arg: &mut S) -> i64 {
177+
42
178+
}
179+
}
180+
181+
pub fn test() {
182+
let x = (&S).foo(); // $ MISSING: target=MyTrait1::foo1 type=x:S
183+
let y = S.foo(); // $ MISSING: target=MyTrait1::foo1 type=y:S
184+
let z = (&mut S).foo(); // $ MISSING: target=MyTrait1::foo2 type=z:i64
185+
186+
let x = S.bar(&S); // $ target=MyTrait2::bar1 type=x:S $ SPURIOUS: target=MyTrait2::bar2
187+
let y = S.bar(&mut S); // $ target=MyTrait2::bar2 type=y:i64 $ SPURIOUS: target=MyTrait2::bar1
188+
}
189+
}
190+
191+
// from https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-search
192+
mod rust_reference_example {
193+
struct Foo {}
194+
195+
trait Bar {
196+
fn bar(&self);
197+
}
198+
199+
impl Foo {
200+
// bar1
201+
fn bar(&mut self) {
202+
println!("In struct impl!")
203+
}
204+
}
205+
206+
impl Bar for Foo {
207+
// bar2
208+
fn bar(&self) {
209+
println!("In trait impl!")
210+
}
211+
}
212+
213+
pub fn main() {
214+
let mut f = Foo {};
215+
f.bar(); // $ SPURIOUS: target=bar1 $ MISSING: target=bar2
216+
}
217+
}
218+
131219
pub fn test() {
132220
explicit_monomorphic_dereference(); // $ target=explicit_monomorphic_dereference
133221
explicit_polymorphic_dereference(); // $ target=explicit_polymorphic_dereference
134222
explicit_ref_dereference(); // $ target=explicit_ref_dereference
135223
explicit_box_dereference(); // $ target=explicit_box_dereference
136224
implicit_dereference(); // $ target=implicit_dereference
137225
implicit_deref_coercion_cycle::test(); // $ target=test
226+
ref_vs_mut_ref::test(); // $ target=test
227+
rust_reference_example::main(); // $ target=main
138228
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// The code in this file is not valid Rust code
2+
3+
// test that our type inference implementation does not run into an infinite loop.
4+
mod type_loop {
5+
struct S<T>(T);
6+
7+
trait T1<T>: T2<S<T>> {
8+
fn foo(self) {}
9+
}
10+
11+
trait T2<T>: T1<S<T>> {
12+
fn bar(self) {
13+
self.foo() // $ target=foo
14+
}
15+
}
16+
}
17+
18+
mod op_blanket_impl {
19+
use std::ops::Add;
20+
21+
#[derive(Debug, Copy, Clone)]
22+
struct Num(i32);
23+
24+
trait AddAlias {
25+
fn add_alias(self, other: Self) -> Self;
26+
}
27+
28+
impl AddAlias for Num {
29+
fn add_alias(self, other: Self) -> Self {
30+
Num(self.0 + other.0) // $ fieldof=Num $ target=add
31+
}
32+
}
33+
34+
// this is not valid in Rust, because of coherence
35+
impl<T: AddAlias> Add for T {
36+
type Output = Self;
37+
38+
// BlanketAdd
39+
fn add(self, other: Self) -> Self {
40+
self.add_alias(other) // $ target=add_alias
41+
}
42+
}
43+
44+
pub fn test_op_blanket() {
45+
let a = Num(5);
46+
let b = Num(10);
47+
let c = a + b; // $ target=BlanketAdd
48+
println!("{c:?}");
49+
}
50+
}
51+
52+
mod impl_specialization {
53+
#[derive(Debug, Copy, Clone)]
54+
struct S1;
55+
56+
trait Clone1 {
57+
fn clone1(&self) -> Self;
58+
}
59+
60+
trait Duplicatable {
61+
fn duplicate(&self) -> Self
62+
where
63+
Self: Sized;
64+
}
65+
66+
impl Clone1 for S1 {
67+
// S1::clone1
68+
fn clone1(&self) -> Self {
69+
*self // $ target=deref
70+
}
71+
}
72+
73+
impl Duplicatable for S1 {
74+
// S1::duplicate
75+
fn duplicate(&self) -> Self {
76+
*self // $ target=deref
77+
}
78+
}
79+
80+
// Blanket implementation for all types that implement Clone1
81+
impl<T: Clone1> Duplicatable for T {
82+
// Clone1duplicate
83+
fn duplicate(&self) -> Self {
84+
self.clone1() // $ target=clone1
85+
}
86+
}
87+
88+
pub fn test_basic_blanket() {
89+
// this call should target the specialized implementation of Duplicatable for S1,
90+
// not the blanket implementation
91+
let x = S1.duplicate(); // $ target=S1::duplicate $ SPURIOUS: target=Clone1duplicate
92+
}
93+
}

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

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)