]> git.lizzy.rs Git - rust.git/blob - tests/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed
Rollup merge of #107248 - erikdesjardins:addrspace, r=oli-obk
[rust.git] / tests / ui / closures / 2229_closure_analysis / migrations / significant_drop.fixed
1 // run-rustfix
2 #![deny(rust_2021_incompatible_closure_captures)]
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, #[allow(unused_tuple_struct_fields)] 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 = || {
26         let _ = (&t, &t1, &t2);
27         //~^ ERROR: drop order
28         //~| NOTE: for more information, see
29         //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
30         let _t = t.0;
31         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
32         let _t1 = t1.0;
33         //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
34         let _t2 = t2.0;
35         //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
36     };
37
38     c();
39 }
40 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
41 //~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
42 //~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
43
44 // String implements drop and therefore should be migrated.
45 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
46 fn test2_only_precise_paths_need_migration() {
47     let t = (Foo(0), Foo(0));
48     let t1 = (Foo(0), Foo(0));
49     let t2 = (Foo(0), Foo(0));
50
51     let c = || {
52         let _ = (&t, &t1);
53         //~^ ERROR: drop order
54         //~| NOTE: for more information, see
55         //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
56         let _t = t.0;
57         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
58         let _t1 = t1.0;
59         //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
60         let _t2 = t2;
61     };
62
63     c();
64 }
65 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
66 //~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
67
68 // If a variable would've not been captured by value then it would've not been
69 // dropped with the closure and therefore doesn't need migration.
70 fn test3_only_by_value_need_migration() {
71     let t = (Foo(0), Foo(0));
72     let t1 = (Foo(0), Foo(0));
73     let c = || {
74         let _ = &t;
75         //~^ ERROR: drop order
76         //~| NOTE: for more information, see
77         //~| HELP: add a dummy let to cause `t` to be fully captured
78         let _t = t.0;
79         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
80         println!("{:?}", t1.1);
81     };
82
83     c();
84 }
85 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
86
87 // The root variable might not implement drop themselves but some path starting
88 // at the root variable might implement Drop.
89 //
90 // If this path isn't captured we need to migrate for the root variable.
91 fn test4_type_contains_drop_need_migration() {
92     let t = ConstainsDropField(Foo(0), Foo(0));
93
94     let c = || {
95         let _ = &t;
96         //~^ ERROR: drop order
97         //~| NOTE: for more information, see
98         //~| HELP: add a dummy let to cause `t` to be fully captured
99         let _t = t.0;
100         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
101     };
102
103     c();
104 }
105 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
106
107 // Test migration analysis in case of Drop + Non Drop aggregates.
108 // Note we need migration here only because the non-copy (because Drop type) is captured,
109 // otherwise we won't need to, since we can get away with just by ref capture in that case.
110 fn test5_drop_non_drop_aggregate_need_migration() {
111     let t = (Foo(0), Foo(0), 0i32);
112
113     let c = || {
114         let _ = &t;
115         //~^ ERROR: drop order
116         //~| NOTE: for more information, see
117         //~| HELP: add a dummy let to cause `t` to be fully captured
118         let _t = t.0;
119         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
120     };
121
122     c();
123 }
124 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
125
126 // Test migration analysis in case of Significant and Insignificant Drop aggregates.
127 fn test6_significant_insignificant_drop_aggregate_need_migration() {
128     let t = (Foo(0), String::new());
129
130     let c = || {
131         let _ = &t;
132         //~^ ERROR: drop order
133         //~| NOTE: for more information, see
134         //~| HELP: add a dummy let to cause `t` to be fully captured
135         let _t = t.1;
136         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
137     };
138
139     c();
140 }
141 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
142
143 // Since we are using a move closure here, both `t` and `t1` get moved
144 // even though they are being used by ref inside the closure.
145 fn test7_move_closures_non_copy_types_might_need_migration() {
146     let t = (Foo(0), Foo(0));
147     let t1 = (Foo(0), Foo(0), Foo(0));
148
149     let c = move || {
150         let _ = (&t1, &t);
151         //~^ ERROR: drop order
152         //~| NOTE: for more information, see
153         //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
154         println!("{:?} {:?}", t1.1, t.1);
155         //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
156         //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
157     };
158
159     c();
160 }
161 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
162 //~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
163
164
165 fn test8_drop_order_and_blocks() {
166     {
167         let tuple =
168           (Foo(0), Foo(1));
169         {
170             let c = || {
171                 let _ = &tuple;
172                 //~^ ERROR: drop order
173                 //~| NOTE: for more information, see
174                 //~| HELP: add a dummy let to cause `tuple` to be fully captured
175                 tuple.0;
176                 //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
177             };
178
179             c();
180         }
181         //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
182     }
183 }
184
185 fn test9_drop_order_and_nested_closures() {
186     let tuple =
187         (Foo(0), Foo(1));
188     let b = || {
189         let c = || {
190             let _ = &tuple;
191             //~^ ERROR: drop order
192             //~| NOTE: for more information, see
193             //~| HELP: add a dummy let to cause `tuple` to be fully captured
194             tuple.0;
195             //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
196         };
197
198         c();
199     };
200     //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
201
202     b();
203 }
204
205 // Test that we migrate if drop order of Vec<T> would be affected if T is a significant drop type
206 fn test10_vec_of_significant_drop_type() {
207
208         let tup = (Foo(0), vec![Foo(3)]);
209
210         let _c = || { let _ = &tup; tup.0 };
211             //~^ ERROR: drop order
212             //~| NOTE: for more information, see
213             //~| HELP: add a dummy let to cause `tup` to be fully captured
214             //~| NOTE: in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0`
215 }
216 //~^ NOTE: in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure
217
218 fn main() {
219     test1_all_need_migration();
220     test2_only_precise_paths_need_migration();
221     test3_only_by_value_need_migration();
222     test4_type_contains_drop_need_migration();
223     test5_drop_non_drop_aggregate_need_migration();
224     test6_significant_insignificant_drop_aggregate_need_migration();
225     test7_move_closures_non_copy_types_might_need_migration();
226     test8_drop_order_and_blocks();
227     test9_drop_order_and_nested_closures();
228     test10_vec_of_significant_drop_type();
229 }