Skip to content

Commit 854639d

Browse files
committed
Rust: Add tests with blanket implementation
1 parent 1fab97b commit 854639d

File tree

3 files changed

+221
-5
lines changed

3 files changed

+221
-5
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Tests for method resolution targeting blanket trait implementations
2+
3+
mod basic_blanket_impl {
4+
#[derive(Debug, Copy, Clone)]
5+
struct S1;
6+
7+
trait Clone1 {
8+
fn clone1(&self) -> Self;
9+
}
10+
11+
trait Duplicatable {
12+
fn duplicate(&self) -> Self
13+
where
14+
Self: Sized;
15+
}
16+
17+
impl Clone1 for S1 {
18+
// S1::clone1
19+
fn clone1(&self) -> Self {
20+
*self // $ target=deref
21+
}
22+
}
23+
24+
// Blanket implementation for all types that implement Display and Clone
25+
impl<T: Clone1> Duplicatable for T {
26+
// Clone1duplicate
27+
fn duplicate(&self) -> Self {
28+
self.clone1() // $ target=clone1
29+
}
30+
}
31+
32+
pub fn test_basic_blanket() {
33+
let x = S1.clone1(); // $ target=S1::clone1
34+
println!("{x:?}");
35+
let y = S1.duplicate(); // $ MISSING: target=Clone1duplicate
36+
println!("{y:?}");
37+
}
38+
}
39+
40+
mod extension_trait_blanket_impl {
41+
// 1. Elements a trait that is implemented for a type parameter
42+
// 2. An extension trait
43+
// 3. A blanket implementation of the extension trait for a type parameter
44+
45+
trait Flag {
46+
fn read_flag(&self) -> bool;
47+
}
48+
49+
trait TryFlag {
50+
fn try_read_flag(&self) -> Option<bool>;
51+
}
52+
53+
impl<Fl> TryFlag for Fl
54+
where
55+
Fl: Flag,
56+
{
57+
fn try_read_flag(&self) -> Option<bool> {
58+
Some(self.read_flag()) // $ target=read_flag
59+
}
60+
}
61+
62+
trait TryFlagExt: TryFlag {
63+
// TryFlagExt::try_read_flag_twice
64+
fn try_read_flag_twice(&self) -> Option<bool> {
65+
self.try_read_flag() // $ target=try_read_flag
66+
}
67+
}
68+
69+
impl<T: TryFlag> TryFlagExt for T {}
70+
71+
trait AnotherTryFlag {
72+
// AnotherTryFlag::try_read_flag_twice
73+
fn try_read_flag_twice(&self) -> Option<bool>;
74+
}
75+
76+
struct MyTryFlag {
77+
flag: bool,
78+
}
79+
80+
impl TryFlag for MyTryFlag {
81+
// MyTryFlag::try_read_flag
82+
fn try_read_flag(&self) -> Option<bool> {
83+
Some(self.flag) // $ fieldof=MyTryFlag
84+
}
85+
}
86+
87+
struct MyFlag {
88+
flag: bool,
89+
}
90+
91+
impl Flag for MyFlag {
92+
// MyFlag::read_flag
93+
fn read_flag(&self) -> bool {
94+
self.flag // $ fieldof=MyFlag
95+
}
96+
}
97+
98+
struct MyOtherFlag {
99+
flag: bool,
100+
}
101+
102+
impl AnotherTryFlag for MyOtherFlag {
103+
// MyOtherFlag::try_read_flag_twice
104+
fn try_read_flag_twice(&self) -> Option<bool> {
105+
Some(self.flag) // $ fieldof=MyOtherFlag
106+
}
107+
}
108+
109+
fn test() {
110+
let my_try_flag = MyTryFlag { flag: true };
111+
let result = my_try_flag.try_read_flag_twice(); // $ MISSING: target=TryFlagExt::try_read_flag_twice
112+
113+
let my_flag = MyFlag { flag: true };
114+
// Here `TryFlagExt::try_read_flag_twice` is since there is a blanket
115+
// implementaton of `TryFlag` for `Flag`.
116+
let result = my_flag.try_read_flag_twice(); // $ MISSING: target=TryFlagExt::try_read_flag_twice
117+
118+
let my_other_flag = MyOtherFlag { flag: true };
119+
// Here `TryFlagExt::try_read_flag_twice` is _not_ a target since
120+
// `MyOtherFlag` does not implement `TryFlag`.
121+
let result = my_other_flag.try_read_flag_twice(); // $ target=MyOtherFlag::try_read_flag_twice
122+
}
123+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,7 @@ pub mod pattern_matching_experimental {
24872487
mod closure;
24882488
mod dereference;
24892489
mod dyn_type;
2490+
mod blanket_impl;
24902491

24912492
fn main() {
24922493
field_access::f(); // $ target=f

rust/ql/test/library-tests/type-inference/type-inference.expected

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,96 @@
11
inferType
2+
| blanket_impl.rs:8:19:8:23 | SelfParam | | file://:0:0:0:0 | & |
3+
| blanket_impl.rs:8:19:8:23 | SelfParam | &T | blanket_impl.rs:7:5:9:5 | Self [trait Clone1] |
4+
| blanket_impl.rs:12:22:12:26 | SelfParam | | file://:0:0:0:0 | & |
5+
| blanket_impl.rs:12:22:12:26 | SelfParam | &T | blanket_impl.rs:11:5:15:5 | Self [trait Duplicatable] |
6+
| blanket_impl.rs:19:19:19:23 | SelfParam | | file://:0:0:0:0 | & |
7+
| blanket_impl.rs:19:19:19:23 | SelfParam | &T | blanket_impl.rs:4:5:5:14 | S1 |
8+
| blanket_impl.rs:19:34:21:9 | { ... } | | blanket_impl.rs:4:5:5:14 | S1 |
9+
| blanket_impl.rs:20:13:20:17 | * ... | | blanket_impl.rs:4:5:5:14 | S1 |
10+
| blanket_impl.rs:20:14:20:17 | self | | file://:0:0:0:0 | & |
11+
| blanket_impl.rs:20:14:20:17 | self | &T | blanket_impl.rs:4:5:5:14 | S1 |
12+
| blanket_impl.rs:27:22:27:26 | SelfParam | | file://:0:0:0:0 | & |
13+
| blanket_impl.rs:27:22:27:26 | SelfParam | &T | blanket_impl.rs:25:10:25:18 | T |
14+
| blanket_impl.rs:27:37:29:9 | { ... } | | blanket_impl.rs:25:10:25:18 | T |
15+
| blanket_impl.rs:28:13:28:16 | self | | file://:0:0:0:0 | & |
16+
| blanket_impl.rs:28:13:28:16 | self | &T | blanket_impl.rs:25:10:25:18 | T |
17+
| blanket_impl.rs:28:13:28:25 | self.clone1() | | blanket_impl.rs:25:10:25:18 | T |
18+
| blanket_impl.rs:33:13:33:13 | x | | blanket_impl.rs:4:5:5:14 | S1 |
19+
| blanket_impl.rs:33:17:33:18 | S1 | | blanket_impl.rs:4:5:5:14 | S1 |
20+
| blanket_impl.rs:33:17:33:27 | S1.clone1() | | blanket_impl.rs:4:5:5:14 | S1 |
21+
| blanket_impl.rs:34:18:34:24 | "{x:?}\\n" | | file://:0:0:0:0 | & |
22+
| blanket_impl.rs:34:18:34:24 | "{x:?}\\n" | &T | {EXTERNAL LOCATION} | str |
23+
| blanket_impl.rs:34:18:34:24 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
24+
| blanket_impl.rs:34:18:34:24 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
25+
| blanket_impl.rs:34:20:34:20 | x | | blanket_impl.rs:4:5:5:14 | S1 |
26+
| blanket_impl.rs:35:17:35:18 | S1 | | blanket_impl.rs:4:5:5:14 | S1 |
27+
| blanket_impl.rs:36:18:36:24 | "{y:?}\\n" | | file://:0:0:0:0 | & |
28+
| blanket_impl.rs:36:18:36:24 | "{y:?}\\n" | &T | {EXTERNAL LOCATION} | str |
29+
| blanket_impl.rs:36:18:36:24 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
30+
| blanket_impl.rs:36:18:36:24 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
31+
| blanket_impl.rs:46:22:46:26 | SelfParam | | file://:0:0:0:0 | & |
32+
| blanket_impl.rs:46:22:46:26 | SelfParam | &T | blanket_impl.rs:45:5:47:5 | Self [trait Flag] |
33+
| blanket_impl.rs:50:26:50:30 | SelfParam | | file://:0:0:0:0 | & |
34+
| blanket_impl.rs:50:26:50:30 | SelfParam | &T | blanket_impl.rs:49:5:51:5 | Self [trait TryFlag] |
35+
| blanket_impl.rs:57:26:57:30 | SelfParam | | file://:0:0:0:0 | & |
36+
| blanket_impl.rs:57:26:57:30 | SelfParam | &T | blanket_impl.rs:53:10:53:11 | Fl |
37+
| blanket_impl.rs:57:49:59:9 | { ... } | | {EXTERNAL LOCATION} | Option |
38+
| blanket_impl.rs:57:49:59:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
39+
| blanket_impl.rs:58:13:58:34 | Some(...) | | {EXTERNAL LOCATION} | Option |
40+
| blanket_impl.rs:58:13:58:34 | Some(...) | T | {EXTERNAL LOCATION} | bool |
41+
| blanket_impl.rs:58:18:58:21 | self | | file://:0:0:0:0 | & |
42+
| blanket_impl.rs:58:18:58:21 | self | &T | blanket_impl.rs:53:10:53:11 | Fl |
43+
| blanket_impl.rs:58:18:58:33 | self.read_flag() | | {EXTERNAL LOCATION} | bool |
44+
| blanket_impl.rs:64:32:64:36 | SelfParam | | file://:0:0:0:0 | & |
45+
| blanket_impl.rs:64:32:64:36 | SelfParam | &T | blanket_impl.rs:62:5:67:5 | Self [trait TryFlagExt] |
46+
| blanket_impl.rs:64:55:66:9 | { ... } | | {EXTERNAL LOCATION} | Option |
47+
| blanket_impl.rs:64:55:66:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
48+
| blanket_impl.rs:65:13:65:16 | self | | file://:0:0:0:0 | & |
49+
| blanket_impl.rs:65:13:65:16 | self | &T | blanket_impl.rs:62:5:67:5 | Self [trait TryFlagExt] |
50+
| blanket_impl.rs:65:13:65:32 | self.try_read_flag() | | {EXTERNAL LOCATION} | Option |
51+
| blanket_impl.rs:65:13:65:32 | self.try_read_flag() | T | {EXTERNAL LOCATION} | bool |
52+
| blanket_impl.rs:73:32:73:36 | SelfParam | | file://:0:0:0:0 | & |
53+
| blanket_impl.rs:73:32:73:36 | SelfParam | &T | blanket_impl.rs:71:5:74:5 | Self [trait AnotherTryFlag] |
54+
| blanket_impl.rs:82:26:82:30 | SelfParam | | file://:0:0:0:0 | & |
55+
| blanket_impl.rs:82:26:82:30 | SelfParam | &T | blanket_impl.rs:76:5:78:5 | MyTryFlag |
56+
| blanket_impl.rs:82:49:84:9 | { ... } | | {EXTERNAL LOCATION} | Option |
57+
| blanket_impl.rs:82:49:84:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
58+
| blanket_impl.rs:83:13:83:27 | Some(...) | | {EXTERNAL LOCATION} | Option |
59+
| blanket_impl.rs:83:13:83:27 | Some(...) | T | {EXTERNAL LOCATION} | bool |
60+
| blanket_impl.rs:83:18:83:21 | self | | file://:0:0:0:0 | & |
61+
| blanket_impl.rs:83:18:83:21 | self | &T | blanket_impl.rs:76:5:78:5 | MyTryFlag |
62+
| blanket_impl.rs:83:18:83:26 | self.flag | | {EXTERNAL LOCATION} | bool |
63+
| blanket_impl.rs:93:22:93:26 | SelfParam | | file://:0:0:0:0 | & |
64+
| blanket_impl.rs:93:22:93:26 | SelfParam | &T | blanket_impl.rs:87:5:89:5 | MyFlag |
65+
| blanket_impl.rs:93:37:95:9 | { ... } | | {EXTERNAL LOCATION} | bool |
66+
| blanket_impl.rs:94:13:94:16 | self | | file://:0:0:0:0 | & |
67+
| blanket_impl.rs:94:13:94:16 | self | &T | blanket_impl.rs:87:5:89:5 | MyFlag |
68+
| blanket_impl.rs:94:13:94:21 | self.flag | | {EXTERNAL LOCATION} | bool |
69+
| blanket_impl.rs:104:32:104:36 | SelfParam | | file://:0:0:0:0 | & |
70+
| blanket_impl.rs:104:32:104:36 | SelfParam | &T | blanket_impl.rs:98:5:100:5 | MyOtherFlag |
71+
| blanket_impl.rs:104:55:106:9 | { ... } | | {EXTERNAL LOCATION} | Option |
72+
| blanket_impl.rs:104:55:106:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
73+
| blanket_impl.rs:105:13:105:27 | Some(...) | | {EXTERNAL LOCATION} | Option |
74+
| blanket_impl.rs:105:13:105:27 | Some(...) | T | {EXTERNAL LOCATION} | bool |
75+
| blanket_impl.rs:105:18:105:21 | self | | file://:0:0:0:0 | & |
76+
| blanket_impl.rs:105:18:105:21 | self | &T | blanket_impl.rs:98:5:100:5 | MyOtherFlag |
77+
| blanket_impl.rs:105:18:105:26 | self.flag | | {EXTERNAL LOCATION} | bool |
78+
| blanket_impl.rs:110:13:110:23 | my_try_flag | | blanket_impl.rs:76:5:78:5 | MyTryFlag |
79+
| blanket_impl.rs:110:27:110:50 | MyTryFlag {...} | | blanket_impl.rs:76:5:78:5 | MyTryFlag |
80+
| blanket_impl.rs:110:45:110:48 | true | | {EXTERNAL LOCATION} | bool |
81+
| blanket_impl.rs:111:22:111:32 | my_try_flag | | blanket_impl.rs:76:5:78:5 | MyTryFlag |
82+
| blanket_impl.rs:113:13:113:19 | my_flag | | blanket_impl.rs:87:5:89:5 | MyFlag |
83+
| blanket_impl.rs:113:23:113:43 | MyFlag {...} | | blanket_impl.rs:87:5:89:5 | MyFlag |
84+
| blanket_impl.rs:113:38:113:41 | true | | {EXTERNAL LOCATION} | bool |
85+
| blanket_impl.rs:116:22:116:28 | my_flag | | blanket_impl.rs:87:5:89:5 | MyFlag |
86+
| blanket_impl.rs:118:13:118:25 | my_other_flag | | blanket_impl.rs:98:5:100:5 | MyOtherFlag |
87+
| blanket_impl.rs:118:29:118:54 | MyOtherFlag {...} | | blanket_impl.rs:98:5:100:5 | MyOtherFlag |
88+
| blanket_impl.rs:118:49:118:52 | true | | {EXTERNAL LOCATION} | bool |
89+
| blanket_impl.rs:121:13:121:18 | result | | {EXTERNAL LOCATION} | Option |
90+
| blanket_impl.rs:121:13:121:18 | result | T | {EXTERNAL LOCATION} | bool |
91+
| blanket_impl.rs:121:22:121:34 | my_other_flag | | blanket_impl.rs:98:5:100:5 | MyOtherFlag |
92+
| blanket_impl.rs:121:22:121:56 | my_other_flag.try_read_flag_twice() | | {EXTERNAL LOCATION} | Option |
93+
| blanket_impl.rs:121:22:121:56 | my_other_flag.try_read_flag_twice() | T | {EXTERNAL LOCATION} | bool |
294
| closure.rs:6:13:6:22 | my_closure | | {EXTERNAL LOCATION} | dyn FnOnce |
395
| closure.rs:6:13:6:22 | my_closure | dyn(Args) | file://:0:0:0:0 | (T_2) |
496
| closure.rs:6:13:6:22 | my_closure | dyn(Args).0(2) | {EXTERNAL LOCATION} | bool |
@@ -4840,11 +4932,11 @@ inferType
48404932
| main.rs:2481:26:2481:43 | "Nested boxed: {}\\n" | &T | {EXTERNAL LOCATION} | str |
48414933
| main.rs:2481:26:2481:59 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
48424934
| main.rs:2481:26:2481:59 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
4843-
| main.rs:2493:5:2493:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo |
4844-
| main.rs:2494:5:2494:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
4845-
| main.rs:2494:20:2494:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
4846-
| main.rs:2494:41:2494:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
4847-
| main.rs:2510:5:2510:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
4935+
| main.rs:2494:5:2494:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo |
4936+
| main.rs:2495:5:2495:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
4937+
| main.rs:2495:20:2495:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
4938+
| main.rs:2495:41:2495:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
4939+
| main.rs:2511:5:2511:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
48484940
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
48494941
| pattern_matching.rs:13:26:133:1 | { ... } | T | file://:0:0:0:0 | () |
48504942
| pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option |

0 commit comments

Comments
 (0)