Skip to content

Commit 69a1c7e

Browse files
committed
Rust: Add tests with blanket implementation
1 parent e8ddac0 commit 69a1c7e

File tree

3 files changed

+222
-5
lines changed

3 files changed

+222
-5
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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+
// This tests:
42+
// 1. A trait that is implemented for a type parameter
43+
// 2. An extension trait
44+
// 3. A blanket implementation of the extension trait for a type parameter
45+
46+
trait Flag {
47+
fn read_flag(&self) -> bool;
48+
}
49+
50+
trait TryFlag {
51+
fn try_read_flag(&self) -> Option<bool>;
52+
}
53+
54+
impl<Fl> TryFlag for Fl
55+
where
56+
Fl: Flag,
57+
{
58+
fn try_read_flag(&self) -> Option<bool> {
59+
Some(self.read_flag()) // $ target=read_flag
60+
}
61+
}
62+
63+
trait TryFlagExt: TryFlag {
64+
// TryFlagExt::try_read_flag_twice
65+
fn try_read_flag_twice(&self) -> Option<bool> {
66+
self.try_read_flag() // $ target=try_read_flag
67+
}
68+
}
69+
70+
impl<T: TryFlag> TryFlagExt for T {}
71+
72+
trait AnotherTryFlag {
73+
// AnotherTryFlag::try_read_flag_twice
74+
fn try_read_flag_twice(&self) -> Option<bool>;
75+
}
76+
77+
struct MyTryFlag {
78+
flag: bool,
79+
}
80+
81+
impl TryFlag for MyTryFlag {
82+
// MyTryFlag::try_read_flag
83+
fn try_read_flag(&self) -> Option<bool> {
84+
Some(self.flag) // $ fieldof=MyTryFlag
85+
}
86+
}
87+
88+
struct MyFlag {
89+
flag: bool,
90+
}
91+
92+
impl Flag for MyFlag {
93+
// MyFlag::read_flag
94+
fn read_flag(&self) -> bool {
95+
self.flag // $ fieldof=MyFlag
96+
}
97+
}
98+
99+
struct MyOtherFlag {
100+
flag: bool,
101+
}
102+
103+
impl AnotherTryFlag for MyOtherFlag {
104+
// MyOtherFlag::try_read_flag_twice
105+
fn try_read_flag_twice(&self) -> Option<bool> {
106+
Some(self.flag) // $ fieldof=MyOtherFlag
107+
}
108+
}
109+
110+
fn test() {
111+
let my_try_flag = MyTryFlag { flag: true };
112+
let result = my_try_flag.try_read_flag_twice(); // $ MISSING: target=TryFlagExt::try_read_flag_twice
113+
114+
let my_flag = MyFlag { flag: true };
115+
// Here `TryFlagExt::try_read_flag_twice` is since there is a blanket
116+
// implementaton of `TryFlag` for `Flag`.
117+
let result = my_flag.try_read_flag_twice(); // $ MISSING: target=TryFlagExt::try_read_flag_twice
118+
119+
let my_other_flag = MyOtherFlag { flag: true };
120+
// Here `TryFlagExt::try_read_flag_twice` is _not_ a target since
121+
// `MyOtherFlag` does not implement `TryFlag`.
122+
let result = my_other_flag.try_read_flag_twice(); // $ target=MyOtherFlag::try_read_flag_twice
123+
}
124+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,7 @@ pub mod path_buf {
26552655
mod closure;
26562656
mod dereference;
26572657
mod dyn_type;
2658+
mod blanket_impl;
26582659

26592660
fn main() {
26602661
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:47:22:47:26 | SelfParam | | file://:0:0:0:0 | & |
32+
| blanket_impl.rs:47:22:47:26 | SelfParam | &T | blanket_impl.rs:46:5:48:5 | Self [trait Flag] |
33+
| blanket_impl.rs:51:26:51:30 | SelfParam | | file://:0:0:0:0 | & |
34+
| blanket_impl.rs:51:26:51:30 | SelfParam | &T | blanket_impl.rs:50:5:52:5 | Self [trait TryFlag] |
35+
| blanket_impl.rs:58:26:58:30 | SelfParam | | file://:0:0:0:0 | & |
36+
| blanket_impl.rs:58:26:58:30 | SelfParam | &T | blanket_impl.rs:54:10:54:11 | Fl |
37+
| blanket_impl.rs:58:49:60:9 | { ... } | | {EXTERNAL LOCATION} | Option |
38+
| blanket_impl.rs:58:49:60:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
39+
| blanket_impl.rs:59:13:59:34 | Some(...) | | {EXTERNAL LOCATION} | Option |
40+
| blanket_impl.rs:59:13:59:34 | Some(...) | T | {EXTERNAL LOCATION} | bool |
41+
| blanket_impl.rs:59:18:59:21 | self | | file://:0:0:0:0 | & |
42+
| blanket_impl.rs:59:18:59:21 | self | &T | blanket_impl.rs:54:10:54:11 | Fl |
43+
| blanket_impl.rs:59:18:59:33 | self.read_flag() | | {EXTERNAL LOCATION} | bool |
44+
| blanket_impl.rs:65:32:65:36 | SelfParam | | file://:0:0:0:0 | & |
45+
| blanket_impl.rs:65:32:65:36 | SelfParam | &T | blanket_impl.rs:63:5:68:5 | Self [trait TryFlagExt] |
46+
| blanket_impl.rs:65:55:67:9 | { ... } | | {EXTERNAL LOCATION} | Option |
47+
| blanket_impl.rs:65:55:67:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
48+
| blanket_impl.rs:66:13:66:16 | self | | file://:0:0:0:0 | & |
49+
| blanket_impl.rs:66:13:66:16 | self | &T | blanket_impl.rs:63:5:68:5 | Self [trait TryFlagExt] |
50+
| blanket_impl.rs:66:13:66:32 | self.try_read_flag() | | {EXTERNAL LOCATION} | Option |
51+
| blanket_impl.rs:66:13:66:32 | self.try_read_flag() | T | {EXTERNAL LOCATION} | bool |
52+
| blanket_impl.rs:74:32:74:36 | SelfParam | | file://:0:0:0:0 | & |
53+
| blanket_impl.rs:74:32:74:36 | SelfParam | &T | blanket_impl.rs:72:5:75:5 | Self [trait AnotherTryFlag] |
54+
| blanket_impl.rs:83:26:83:30 | SelfParam | | file://:0:0:0:0 | & |
55+
| blanket_impl.rs:83:26:83:30 | SelfParam | &T | blanket_impl.rs:77:5:79:5 | MyTryFlag |
56+
| blanket_impl.rs:83:49:85:9 | { ... } | | {EXTERNAL LOCATION} | Option |
57+
| blanket_impl.rs:83:49:85:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
58+
| blanket_impl.rs:84:13:84:27 | Some(...) | | {EXTERNAL LOCATION} | Option |
59+
| blanket_impl.rs:84:13:84:27 | Some(...) | T | {EXTERNAL LOCATION} | bool |
60+
| blanket_impl.rs:84:18:84:21 | self | | file://:0:0:0:0 | & |
61+
| blanket_impl.rs:84:18:84:21 | self | &T | blanket_impl.rs:77:5:79:5 | MyTryFlag |
62+
| blanket_impl.rs:84:18:84:26 | self.flag | | {EXTERNAL LOCATION} | bool |
63+
| blanket_impl.rs:94:22:94:26 | SelfParam | | file://:0:0:0:0 | & |
64+
| blanket_impl.rs:94:22:94:26 | SelfParam | &T | blanket_impl.rs:88:5:90:5 | MyFlag |
65+
| blanket_impl.rs:94:37:96:9 | { ... } | | {EXTERNAL LOCATION} | bool |
66+
| blanket_impl.rs:95:13:95:16 | self | | file://:0:0:0:0 | & |
67+
| blanket_impl.rs:95:13:95:16 | self | &T | blanket_impl.rs:88:5:90:5 | MyFlag |
68+
| blanket_impl.rs:95:13:95:21 | self.flag | | {EXTERNAL LOCATION} | bool |
69+
| blanket_impl.rs:105:32:105:36 | SelfParam | | file://:0:0:0:0 | & |
70+
| blanket_impl.rs:105:32:105:36 | SelfParam | &T | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
71+
| blanket_impl.rs:105:55:107:9 | { ... } | | {EXTERNAL LOCATION} | Option |
72+
| blanket_impl.rs:105:55:107:9 | { ... } | T | {EXTERNAL LOCATION} | bool |
73+
| blanket_impl.rs:106:13:106:27 | Some(...) | | {EXTERNAL LOCATION} | Option |
74+
| blanket_impl.rs:106:13:106:27 | Some(...) | T | {EXTERNAL LOCATION} | bool |
75+
| blanket_impl.rs:106:18:106:21 | self | | file://:0:0:0:0 | & |
76+
| blanket_impl.rs:106:18:106:21 | self | &T | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
77+
| blanket_impl.rs:106:18:106:26 | self.flag | | {EXTERNAL LOCATION} | bool |
78+
| blanket_impl.rs:111:13:111:23 | my_try_flag | | blanket_impl.rs:77:5:79:5 | MyTryFlag |
79+
| blanket_impl.rs:111:27:111:50 | MyTryFlag {...} | | blanket_impl.rs:77:5:79:5 | MyTryFlag |
80+
| blanket_impl.rs:111:45:111:48 | true | | {EXTERNAL LOCATION} | bool |
81+
| blanket_impl.rs:112:22:112:32 | my_try_flag | | blanket_impl.rs:77:5:79:5 | MyTryFlag |
82+
| blanket_impl.rs:114:13:114:19 | my_flag | | blanket_impl.rs:88:5:90:5 | MyFlag |
83+
| blanket_impl.rs:114:23:114:43 | MyFlag {...} | | blanket_impl.rs:88:5:90:5 | MyFlag |
84+
| blanket_impl.rs:114:38:114:41 | true | | {EXTERNAL LOCATION} | bool |
85+
| blanket_impl.rs:117:22:117:28 | my_flag | | blanket_impl.rs:88:5:90:5 | MyFlag |
86+
| blanket_impl.rs:119:13:119:25 | my_other_flag | | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
87+
| blanket_impl.rs:119:29:119:54 | MyOtherFlag {...} | | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
88+
| blanket_impl.rs:119:49:119:52 | true | | {EXTERNAL LOCATION} | bool |
89+
| blanket_impl.rs:122:13:122:18 | result | | {EXTERNAL LOCATION} | Option |
90+
| blanket_impl.rs:122:13:122:18 | result | T | {EXTERNAL LOCATION} | bool |
91+
| blanket_impl.rs:122:22:122:34 | my_other_flag | | blanket_impl.rs:99:5:101:5 | MyOtherFlag |
92+
| blanket_impl.rs:122:22:122:56 | my_other_flag.try_read_flag_twice() | | {EXTERNAL LOCATION} | Option |
93+
| blanket_impl.rs:122:22:122: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 |
@@ -5000,11 +5092,11 @@ inferType
50005092
| main.rs:2649:13:2649:20 | pathbuf1 | | main.rs:2624:5:2624:25 | PathBuf |
50015093
| main.rs:2649:24:2649:37 | ...::new(...) | | main.rs:2624:5:2624:25 | PathBuf |
50025094
| main.rs:2650:24:2650:31 | pathbuf1 | | main.rs:2624:5:2624:25 | PathBuf |
5003-
| main.rs:2661:5:2661:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo |
5004-
| main.rs:2662:5:2662:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
5005-
| main.rs:2662:20:2662:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
5006-
| main.rs:2662:41:2662:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
5007-
| main.rs:2678:5:2678:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
5095+
| main.rs:2662:5:2662:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo |
5096+
| main.rs:2663:5:2663:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
5097+
| main.rs:2663:20:2663:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
5098+
| main.rs:2663:41:2663:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
5099+
| main.rs:2679:5:2679:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
50085100
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
50095101
| pattern_matching.rs:13:26:133:1 | { ... } | T | file://:0:0:0:0 | () |
50105102
| pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option |

0 commit comments

Comments
 (0)