]>
Commit | Line | Data |
---|---|---|
cdc7bbd5 | 1 | // run-rustfix |
136023e0 | 2 | #![deny(rust_2021_incompatible_closure_captures)] |
cdc7bbd5 XL |
3 | //~^ NOTE: the lint level is defined here |
4 | ||
5 | // Test cases for types that implement a significant drop (user defined) | |
6 | ||
7 | #[derive(Debug)] | |
8 | struct Foo(i32); | |
9 | impl Drop for Foo { | |
10 | fn drop(&mut self) { | |
11 | println!("{:?} dropped", self.0); | |
12 | } | |
13 | } | |
14 | ||
15 | #[derive(Debug)] | |
16 | struct ConstainsDropField(Foo, Foo); | |
17 | ||
18 | // `t` needs Drop because one of its elements needs drop, | |
19 | // therefore precise capture might affect drop ordering | |
20 | fn test1_all_need_migration() { | |
21 | let t = (Foo(0), Foo(0)); | |
22 | let t1 = (Foo(0), Foo(0)); | |
23 | let t2 = (Foo(0), Foo(0)); | |
24 | ||
25 | let c = || { let _ = (&t, &t1, &t2); | |
136023e0 XL |
26 | //~^ ERROR: drop order |
27 | //~| NOTE: for more information, see | |
28 | //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured | |
cdc7bbd5 | 29 | let _t = t.0; |
136023e0 | 30 | //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` |
cdc7bbd5 | 31 | let _t1 = t1.0; |
136023e0 | 32 | //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` |
cdc7bbd5 | 33 | let _t2 = t2.0; |
136023e0 | 34 | //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` |
cdc7bbd5 XL |
35 | }; |
36 | ||
37 | c(); | |
38 | } | |
136023e0 XL |
39 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure |
40 | //~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure | |
41 | //~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure | |
cdc7bbd5 XL |
42 | |
43 | // String implements drop and therefore should be migrated. | |
44 | // But in this test cases, `t2` is completely captured and when it is dropped won't be affected | |
45 | fn test2_only_precise_paths_need_migration() { | |
46 | let t = (Foo(0), Foo(0)); | |
47 | let t1 = (Foo(0), Foo(0)); | |
48 | let t2 = (Foo(0), Foo(0)); | |
49 | ||
50 | let c = || { let _ = (&t, &t1); | |
136023e0 XL |
51 | //~^ ERROR: drop order |
52 | //~| NOTE: for more information, see | |
53 | //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured | |
cdc7bbd5 | 54 | let _t = t.0; |
136023e0 | 55 | //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` |
cdc7bbd5 | 56 | let _t1 = t1.0; |
136023e0 | 57 | //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` |
cdc7bbd5 XL |
58 | let _t2 = t2; |
59 | }; | |
60 | ||
61 | c(); | |
62 | } | |
136023e0 XL |
63 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure |
64 | //~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure | |
cdc7bbd5 XL |
65 | |
66 | // If a variable would've not been captured by value then it would've not been | |
67 | // dropped with the closure and therefore doesn't need migration. | |
68 | fn test3_only_by_value_need_migration() { | |
69 | let t = (Foo(0), Foo(0)); | |
70 | let t1 = (Foo(0), Foo(0)); | |
71 | let c = || { let _ = &t; | |
136023e0 XL |
72 | //~^ ERROR: drop order |
73 | //~| NOTE: for more information, see | |
74 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
cdc7bbd5 | 75 | let _t = t.0; |
136023e0 | 76 | //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` |
cdc7bbd5 XL |
77 | println!("{:?}", t1.1); |
78 | }; | |
79 | ||
80 | c(); | |
81 | } | |
136023e0 | 82 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure |
cdc7bbd5 XL |
83 | |
84 | // The root variable might not implement drop themselves but some path starting | |
85 | // at the root variable might implement Drop. | |
86 | // | |
87 | // If this path isn't captured we need to migrate for the root variable. | |
88 | fn test4_type_contains_drop_need_migration() { | |
89 | let t = ConstainsDropField(Foo(0), Foo(0)); | |
90 | ||
91 | let c = || { let _ = &t; | |
136023e0 XL |
92 | //~^ ERROR: drop order |
93 | //~| NOTE: for more information, see | |
94 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
cdc7bbd5 | 95 | let _t = t.0; |
136023e0 | 96 | //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` |
cdc7bbd5 XL |
97 | }; |
98 | ||
99 | c(); | |
100 | } | |
136023e0 | 101 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure |
cdc7bbd5 XL |
102 | |
103 | // Test migration analysis in case of Drop + Non Drop aggregates. | |
104 | // Note we need migration here only because the non-copy (because Drop type) is captured, | |
105 | // otherwise we won't need to, since we can get away with just by ref capture in that case. | |
106 | fn test5_drop_non_drop_aggregate_need_migration() { | |
107 | let t = (Foo(0), Foo(0), 0i32); | |
108 | ||
109 | let c = || { let _ = &t; | |
136023e0 XL |
110 | //~^ ERROR: drop order |
111 | //~| NOTE: for more information, see | |
112 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
cdc7bbd5 | 113 | let _t = t.0; |
136023e0 | 114 | //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` |
cdc7bbd5 XL |
115 | }; |
116 | ||
117 | c(); | |
118 | } | |
136023e0 | 119 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure |
cdc7bbd5 XL |
120 | |
121 | // Test migration analysis in case of Significant and Insignificant Drop aggregates. | |
122 | fn test6_significant_insignificant_drop_aggregate_need_migration() { | |
123 | let t = (Foo(0), String::new()); | |
124 | ||
125 | let c = || { let _ = &t; | |
136023e0 XL |
126 | //~^ ERROR: drop order |
127 | //~| NOTE: for more information, see | |
128 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
cdc7bbd5 | 129 | let _t = t.1; |
136023e0 | 130 | //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` |
cdc7bbd5 XL |
131 | }; |
132 | ||
133 | c(); | |
134 | } | |
136023e0 | 135 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure |
cdc7bbd5 XL |
136 | |
137 | // Since we are using a move closure here, both `t` and `t1` get moved | |
138 | // even though they are being used by ref inside the closure. | |
139 | fn test7_move_closures_non_copy_types_might_need_migration() { | |
140 | let t = (Foo(0), Foo(0)); | |
141 | let t1 = (Foo(0), Foo(0), Foo(0)); | |
142 | ||
143 | let c = move || { let _ = (&t1, &t); | |
136023e0 XL |
144 | //~^ ERROR: drop order |
145 | //~| NOTE: for more information, see | |
146 | //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured | |
cdc7bbd5 | 147 | println!("{:?} {:?}", t1.1, t.1); |
136023e0 XL |
148 | //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` |
149 | //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` | |
cdc7bbd5 XL |
150 | }; |
151 | ||
152 | c(); | |
153 | } | |
136023e0 XL |
154 | //~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure |
155 | //~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure | |
156 | ||
157 | ||
158 | fn test8_drop_order_and_blocks() { | |
159 | { | |
160 | let tuple = | |
161 | (String::from("foo"), String::from("bar")); | |
162 | { | |
163 | let c = || { let _ = &tuple; | |
164 | //~^ ERROR: drop order | |
165 | //~| NOTE: for more information, see | |
166 | //~| HELP: add a dummy let to cause `tuple` to be fully captured | |
167 | tuple.0; | |
168 | //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` | |
169 | }; | |
170 | ||
171 | c(); | |
172 | } | |
173 | //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure | |
174 | } | |
175 | } | |
176 | ||
177 | fn test9_drop_order_and_nested_closures() { | |
178 | let tuple = | |
179 | (String::from("foo"), String::from("bar")); | |
180 | let b = || { | |
181 | let c = || { let _ = &tuple; | |
182 | //~^ ERROR: drop order | |
183 | //~| NOTE: for more information, see | |
184 | //~| HELP: add a dummy let to cause `tuple` to be fully captured | |
185 | tuple.0; | |
186 | //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` | |
187 | }; | |
188 | ||
189 | c(); | |
190 | }; | |
191 | //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure | |
192 | ||
193 | b(); | |
194 | } | |
cdc7bbd5 XL |
195 | |
196 | fn main() { | |
197 | test1_all_need_migration(); | |
198 | test2_only_precise_paths_need_migration(); | |
199 | test3_only_by_value_need_migration(); | |
200 | test4_type_contains_drop_need_migration(); | |
201 | test5_drop_non_drop_aggregate_need_migration(); | |
202 | test6_significant_insignificant_drop_aggregate_need_migration(); | |
203 | test7_move_closures_non_copy_types_might_need_migration(); | |
136023e0 XL |
204 | test8_drop_order_and_blocks(); |
205 | test9_drop_order_and_nested_closures(); | |
cdc7bbd5 | 206 | } |