]> git.lizzy.rs Git - rust.git/blob - tests/ui/closures/2229_closure_analysis/move_closure.rs
Rollup merge of #106144 - tgross35:patch-1, r=Mark-Simulacrum
[rust.git] / tests / ui / closures / 2229_closure_analysis / move_closure.rs
1 // edition:2021
2
3 // Test that move closures drop derefs with `capture_disjoint_fields` enabled.
4
5 #![feature(rustc_attrs)]
6
7 fn simple_move_closure() {
8     struct S(String);
9     struct T(S);
10
11     let t = T(S("s".into()));
12     let mut c = #[rustc_capture_analysis]
13     //~^ ERROR: attributes on expressions are experimental
14     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
15     move || {
16     //~^ ERROR: First Pass analysis includes:
17     //~| ERROR: Min Capture analysis includes:
18         t.0.0 = "new S".into();
19         //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
20         //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
21     };
22     c();
23 }
24
25 // Test move closure use reborrows when using references
26 fn simple_ref() {
27     let mut s = 10;
28     let ref_s = &mut s;
29
30     let mut c = #[rustc_capture_analysis]
31     //~^ ERROR: attributes on expressions are experimental
32     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
33     move || {
34     //~^ ERROR: First Pass analysis includes:
35     //~| ERROR: Min Capture analysis includes:
36         *ref_s += 10;
37         //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow
38         //~| NOTE: Min Capture ref_s[] -> ByValue
39     };
40     c();
41 }
42
43 // Test move closure use reborrows when using references
44 fn struct_contains_ref_to_another_struct_1() {
45     struct S(String);
46     struct T<'a>(&'a mut S);
47
48     let mut s = S("s".into());
49     let t = T(&mut s);
50
51     let mut c = #[rustc_capture_analysis]
52     //~^ ERROR: attributes on expressions are experimental
53     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
54     move || {
55     //~^ ERROR: First Pass analysis includes:
56     //~| ERROR: Min Capture analysis includes:
57         t.0.0 = "new s".into();
58         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
59         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
60     };
61
62     c();
63 }
64
65 // Test that we can use reborrows to read data of Copy types
66 // i.e. without truncating derefs
67 fn struct_contains_ref_to_another_struct_2() {
68     struct S(i32);
69     struct T<'a>(&'a S);
70
71     let s = S(0);
72     let t = T(&s);
73
74     let mut c = #[rustc_capture_analysis]
75     //~^ ERROR: attributes on expressions are experimental
76     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
77     move || {
78     //~^ ERROR: First Pass analysis includes:
79     //~| ERROR: Min Capture analysis includes:
80         let _t = t.0.0;
81         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
82         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
83     };
84
85     c();
86 }
87
88 // Test that we can use truncate to move out of !Copy types
89 fn struct_contains_ref_to_another_struct_3() {
90     struct S(String);
91     struct T<'a>(&'a S);
92
93     let s = S("s".into());
94     let t = T(&s);
95
96     let mut c = #[rustc_capture_analysis]
97     //~^ ERROR: attributes on expressions are experimental
98     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
99     move || {
100     //~^ ERROR: First Pass analysis includes:
101     //~| ERROR: Min Capture analysis includes:
102         let _t = t.0.0;
103         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
104         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
105     };
106
107     c();
108 }
109
110 // Test that derefs of box are truncated in move closures
111 fn truncate_box_derefs() {
112     struct S(i32);
113
114
115     // Content within the box is moved within the closure
116     let b = Box::new(S(10));
117     let c = #[rustc_capture_analysis]
118     //~^ ERROR: attributes on expressions are experimental
119     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
120     move || {
121     //~^ ERROR: First Pass analysis includes:
122     //~| ERROR: Min Capture analysis includes:
123         let _t = b.0;
124         //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
125         //~| NOTE: Min Capture b[] -> ByValue
126     };
127
128     c();
129
130     // Content within the box is used by a shared ref and the box is the root variable
131     let b = Box::new(S(10));
132
133     let c = #[rustc_capture_analysis]
134     //~^ ERROR: attributes on expressions are experimental
135     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
136     move || {
137     //~^ ERROR: First Pass analysis includes:
138     //~| ERROR: Min Capture analysis includes:
139         println!("{}", b.0);
140         //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
141         //~| NOTE: Min Capture b[] -> ByValue
142     };
143
144     c();
145
146     // Content within the box is used by a shared ref and the box is not the root variable
147     let b = Box::new(S(10));
148     let t = (0, b);
149
150     let c = #[rustc_capture_analysis]
151     //~^ ERROR: attributes on expressions are experimental
152     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
153     move || {
154     //~^ ERROR: First Pass analysis includes:
155     //~| ERROR: Min Capture analysis includes:
156         println!("{}", t.1.0);
157         //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
158         //~| NOTE: Min Capture t[(1, 0)] -> ByValue
159     };
160 }
161
162 struct Foo { x: i32 }
163
164 // Ensure that even in move closures, if the data is not owned by the root variable
165 // then we don't truncate the derefs or a ByValue capture, rather do a reborrow
166 fn box_mut_1() {
167     let mut foo = Foo { x: 0 } ;
168
169     let p_foo = &mut foo;
170     let box_p_foo = Box::new(p_foo);
171
172     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
173     //~^ ERROR: attributes on expressions are experimental
174     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
175     //~| First Pass analysis includes:
176     //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
177     //~| Min Capture analysis includes:
178     //~| NOTE: Min Capture box_p_foo[] -> ByValue
179 }
180
181 // Ensure that even in move closures, if the data is not owned by the root variable
182 // then we don't truncate the derefs or a ByValue capture, rather do a reborrow
183 fn box_mut_2() {
184     let foo = Foo { x: 0 } ;
185
186     let mut box_foo = Box::new(foo);
187     let p_foo = &mut box_foo;
188
189     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
190     //~^ ERROR: attributes on expressions are experimental
191     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
192     //~| First Pass analysis includes:
193     //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
194     //~| Min Capture analysis includes:
195     //~| NOTE: Min Capture p_foo[] -> ByValue
196 }
197
198 // Test that move closures can take ownership of Copy type
199 fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 {
200     let x = 10;
201
202     let c = #[rustc_capture_analysis] move || x;
203     //~^ ERROR: attributes on expressions are experimental
204     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
205     //~| First Pass analysis includes:
206     //~| NOTE: Capturing x[] -> ImmBorrow
207     //~| Min Capture analysis includes:
208     //~| NOTE: Min Capture x[] -> ByValue
209
210     c
211 }
212
213 fn main() {
214     simple_move_closure();
215     simple_ref();
216     struct_contains_ref_to_another_struct_1();
217     struct_contains_ref_to_another_struct_2();
218     struct_contains_ref_to_another_struct_3();
219     truncate_box_derefs();
220     box_mut_2();
221     box_mut_1();
222 }