]> git.lizzy.rs Git - rust.git/blob - tests/ui/closures/2229_closure_analysis/migrations/significant_drop.rs
Rollup merge of #106570 - Xaeroxe:div-duration-tests, r=JohnTitor
[rust.git] / tests / ui / closures / 2229_closure_analysis / migrations / significant_drop.rs
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         //~^ ERROR: drop order
27         //~| NOTE: for more information, see
28         //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
29         let _t = t.0;
30         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
31         let _t1 = t1.0;
32         //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
33         let _t2 = t2.0;
34         //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
35     };
36
37     c();
38 }
39 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
40 //~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
41 //~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
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 = || {
51         //~^ ERROR: drop order
52         //~| NOTE: for more information, see
53         //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
54         let _t = t.0;
55         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
56         let _t1 = t1.0;
57         //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
58         let _t2 = t2;
59     };
60
61     c();
62 }
63 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
64 //~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
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 = || {
72         //~^ ERROR: drop order
73         //~| NOTE: for more information, see
74         //~| HELP: add a dummy let to cause `t` to be fully captured
75         let _t = t.0;
76         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
77         println!("{:?}", t1.1);
78     };
79
80     c();
81 }
82 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
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 = || {
92         //~^ ERROR: drop order
93         //~| NOTE: for more information, see
94         //~| HELP: add a dummy let to cause `t` to be fully captured
95         let _t = t.0;
96         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
97     };
98
99     c();
100 }
101 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
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 = || {
110         //~^ ERROR: drop order
111         //~| NOTE: for more information, see
112         //~| HELP: add a dummy let to cause `t` to be fully captured
113         let _t = t.0;
114         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
115     };
116
117     c();
118 }
119 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
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 = || {
126         //~^ ERROR: drop order
127         //~| NOTE: for more information, see
128         //~| HELP: add a dummy let to cause `t` to be fully captured
129         let _t = t.1;
130         //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
131     };
132
133     c();
134 }
135 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
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 || {
144         //~^ ERROR: drop order
145         //~| NOTE: for more information, see
146         //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
147         println!("{:?} {:?}", t1.1, t.1);
148         //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
149         //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
150     };
151
152     c();
153 }
154 //~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
155 //~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
156
157
158 fn test8_drop_order_and_blocks() {
159     {
160         let tuple =
161           (Foo(0), Foo(1));
162         {
163             let c = || {
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, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
169             };
170
171             c();
172         }
173         //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
174     }
175 }
176
177 fn test9_drop_order_and_nested_closures() {
178     let tuple =
179         (Foo(0), Foo(1));
180     let b = || {
181         let c = || {
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, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
187         };
188
189         c();
190     };
191     //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
192
193     b();
194 }
195
196 // Test that we migrate if drop order of Vec<T> would be affected if T is a significant drop type
197 fn test10_vec_of_significant_drop_type() {
198
199         let tup = (Foo(0), vec![Foo(3)]);
200
201         let _c = || tup.0;
202             //~^ ERROR: drop order
203             //~| NOTE: for more information, see
204             //~| HELP: add a dummy let to cause `tup` to be fully captured
205             //~| NOTE: in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0`
206 }
207 //~^ NOTE: in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure
208
209 fn main() {
210     test1_all_need_migration();
211     test2_only_precise_paths_need_migration();
212     test3_only_by_value_need_migration();
213     test4_type_contains_drop_need_migration();
214     test5_drop_non_drop_aggregate_need_migration();
215     test6_significant_insignificant_drop_aggregate_need_migration();
216     test7_move_closures_non_copy_types_might_need_migration();
217     test8_drop_order_and_blocks();
218     test9_drop_order_and_nested_closures();
219     test10_vec_of_significant_drop_type();
220 }