]>
Commit | Line | Data |
---|---|---|
cdc7bbd5 | 1 | // run-rustfix |
5869c6ff XL |
2 | #![deny(disjoint_capture_drop_reorder)] |
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 = || { | |
cdc7bbd5 XL |
26 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
27 | //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured | |
5869c6ff XL |
28 | let _t = t.0; |
29 | let _t1 = t1.0; | |
30 | let _t2 = t2.0; | |
31 | }; | |
32 | ||
33 | c(); | |
34 | } | |
35 | ||
36 | // String implements drop and therefore should be migrated. | |
37 | // But in this test cases, `t2` is completely captured and when it is dropped won't be affected | |
38 | fn test2_only_precise_paths_need_migration() { | |
39 | let t = (Foo(0), Foo(0)); | |
40 | let t1 = (Foo(0), Foo(0)); | |
41 | let t2 = (Foo(0), Foo(0)); | |
42 | ||
43 | let c = || { | |
cdc7bbd5 XL |
44 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
45 | //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured | |
5869c6ff XL |
46 | let _t = t.0; |
47 | let _t1 = t1.0; | |
48 | let _t2 = t2; | |
49 | }; | |
50 | ||
51 | c(); | |
52 | } | |
53 | ||
54 | // If a variable would've not been captured by value then it would've not been | |
55 | // dropped with the closure and therefore doesn't need migration. | |
56 | fn test3_only_by_value_need_migration() { | |
57 | let t = (Foo(0), Foo(0)); | |
58 | let t1 = (Foo(0), Foo(0)); | |
59 | let c = || { | |
cdc7bbd5 XL |
60 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
61 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
5869c6ff XL |
62 | let _t = t.0; |
63 | println!("{:?}", t1.1); | |
64 | }; | |
65 | ||
66 | c(); | |
67 | } | |
68 | ||
69 | // The root variable might not implement drop themselves but some path starting | |
70 | // at the root variable might implement Drop. | |
71 | // | |
72 | // If this path isn't captured we need to migrate for the root variable. | |
73 | fn test4_type_contains_drop_need_migration() { | |
74 | let t = ConstainsDropField(Foo(0), Foo(0)); | |
75 | ||
76 | let c = || { | |
cdc7bbd5 XL |
77 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
78 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
5869c6ff XL |
79 | let _t = t.0; |
80 | }; | |
81 | ||
82 | c(); | |
83 | } | |
84 | ||
85 | // Test migration analysis in case of Drop + Non Drop aggregates. | |
86 | // Note we need migration here only because the non-copy (because Drop type) is captured, | |
87 | // otherwise we won't need to, since we can get away with just by ref capture in that case. | |
88 | fn test5_drop_non_drop_aggregate_need_migration() { | |
89 | let t = (Foo(0), Foo(0), 0i32); | |
90 | ||
91 | let c = || { | |
cdc7bbd5 XL |
92 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
93 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
5869c6ff XL |
94 | let _t = t.0; |
95 | }; | |
96 | ||
97 | c(); | |
98 | } | |
99 | ||
100 | // Test migration analysis in case of Significant and Insignificant Drop aggregates. | |
101 | fn test6_significant_insignificant_drop_aggregate_need_migration() { | |
5869c6ff XL |
102 | let t = (Foo(0), String::new()); |
103 | ||
104 | let c = || { | |
cdc7bbd5 XL |
105 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
106 | //~| HELP: add a dummy let to cause `t` to be fully captured | |
5869c6ff XL |
107 | let _t = t.1; |
108 | }; | |
109 | ||
110 | c(); | |
111 | } | |
112 | ||
113 | // Since we are using a move closure here, both `t` and `t1` get moved | |
114 | // even though they are being used by ref inside the closure. | |
115 | fn test7_move_closures_non_copy_types_might_need_migration() { | |
116 | let t = (Foo(0), Foo(0)); | |
117 | let t1 = (Foo(0), Foo(0), Foo(0)); | |
118 | ||
119 | let c = move || { | |
cdc7bbd5 XL |
120 | //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` |
121 | //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured | |
5869c6ff XL |
122 | println!("{:?} {:?}", t1.1, t.1); |
123 | }; | |
124 | ||
125 | c(); | |
126 | } | |
127 | ||
128 | fn main() { | |
129 | test1_all_need_migration(); | |
130 | test2_only_precise_paths_need_migration(); | |
131 | test3_only_by_value_need_migration(); | |
132 | test4_type_contains_drop_need_migration(); | |
133 | test5_drop_non_drop_aggregate_need_migration(); | |
134 | test6_significant_insignificant_drop_aggregate_need_migration(); | |
135 | test7_move_closures_non_copy_types_might_need_migration(); | |
136 | } |