]> git.lizzy.rs Git - rust.git/blob - src/test/ui/nll/issue-21232-partial-init-and-use.rs
Rollup merge of #61389 - Zoxc:arena-cleanup, r=eddyb
[rust.git] / src / test / ui / nll / issue-21232-partial-init-and-use.rs
1 // This test enumerates various cases of interest for partial
2 // [re]initialization of ADTs and tuples.
3 //
4 // See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987.
5 //
6 // All of tests in this file are expected to change from being
7 // rejected, at least under NLL (by rust-lang/rust#54986) to being
8 // **accepted** when rust-lang/rust#54987 is implemented.
9 // (That's why there are assertions in the code.)
10 //
11 // See issue-21232-partial-init-and-erroneous-use.rs for cases of
12 // tests that are meant to continue failing to compile once
13 // rust-lang/rust#54987 is implemented.
14
15 #![feature(nll)]
16
17 struct S<Y> {
18     x: u32,
19
20     // Note that even though `y` may implement `Drop`, under #54987 we
21     // will still allow partial initialization of `S` itself.
22     y: Y,
23 }
24
25 enum Void { }
26
27 type B = Box<u32>;
28
29 impl S<B> { fn new() -> Self { S { x: 0, y: Box::new(0) } } }
30
31 fn borrow_s(s: &S<B>) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
32 fn move_s(s: S<B>) {  assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
33 fn borrow_field(x: &u32) { assert_eq!(*x, 10); }
34
35 type T = (u32, B);
36 type Tvoid = (u32, Void);
37
38 fn borrow_t(t: &T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
39 fn move_t(t: T) {  assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
40
41 struct Q<F> {
42     v: u32,
43     r: R<F>,
44 }
45
46 struct R<F> {
47     w: u32,
48     f: F,
49 }
50
51 impl<F> Q<F> { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } }
52 impl<F> R<F> { fn new(f: F) -> Self { R { w: 0, f } } }
53
54 // Axes to cover:
55 // * local/field: Is the structure in a local or a field
56 // * fully/partial/void: Are we fully initializing it before using any part?
57 //                       Is whole type empty due to a void component?
58 // * init/reinit: First initialization, or did we previously inititalize and then move out?
59 // * struct/tuple: Is this a struct or a (X, Y).
60 //
61 // As a shorthand for the cases above, adding a numeric summary to
62 // each test's fn name to denote each point on each axis.
63 //
64 // e.g., 1000 = field fully init struct; 0211 = local void reinit tuple
65
66 // It got pretty monotonous writing the same code over and over, and I
67 // feared I would forget details. So I abstracted some desiderata into
68 // macros. But I left the initialization code inline, because that's
69 // where the errors for #54986 will be emitted.
70
71 macro_rules! use_fully {
72     (struct $s:expr) => { {
73         borrow_field(& $s.x );
74         borrow_s(& $s );
75         move_s( $s );
76     } };
77
78     (tuple $t:expr) => { {
79         borrow_field(& $t.0 );
80         borrow_t(& $t );
81         move_t( $t );
82     } }
83 }
84
85 macro_rules! use_part {
86     (struct $s:expr) => { {
87         borrow_field(& $s.x );
88         match $s { S { ref x, y: _ } => { borrow_field(x); } }
89     } };
90
91     (tuple $t:expr) => { {
92         borrow_field(& $t.0 );
93         match $t { (ref x, _) => { borrow_field(x); } }
94     } }
95 }
96
97 fn test_0000_local_fully_init_and_use_struct() {
98     let s: S<B>;
99     s.x = 10; s.y = Box::new(20);
100     //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
101     use_fully!(struct s);
102 }
103
104 fn test_0001_local_fully_init_and_use_tuple() {
105     let t: T;
106     t.0 = 10; t.1 = Box::new(20);
107     //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
108     use_fully!(tuple t);
109 }
110
111 fn test_0010_local_fully_reinit_and_use_struct() {
112     let mut s: S<B> = S::new(); drop(s);
113     s.x = 10; s.y = Box::new(20);
114     //~^ ERROR assign to part of moved value: `s` [E0382]
115     use_fully!(struct s);
116 }
117
118 fn test_0011_local_fully_reinit_and_use_tuple() {
119     let mut t: T = (0, Box::new(0)); drop(t);
120     t.0 = 10; t.1 = Box::new(20);
121     //~^ ERROR assign to part of moved value: `t` [E0382]
122     use_fully!(tuple t);
123 }
124
125 fn test_0100_local_partial_init_and_use_struct() {
126     let s: S<B>;
127     s.x = 10;
128     //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
129     use_part!(struct s);
130 }
131
132 fn test_0101_local_partial_init_and_use_tuple() {
133     let t: T;
134     t.0 = 10;
135     //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
136     use_part!(tuple t);
137 }
138
139 fn test_0110_local_partial_reinit_and_use_struct() {
140     let mut s: S<B> = S::new(); drop(s);
141     s.x = 10;
142     //~^ ERROR assign to part of moved value: `s` [E0382]
143     use_part!(struct s);
144 }
145
146 fn test_0111_local_partial_reinit_and_use_tuple() {
147     let mut t: T = (0, Box::new(0)); drop(t);
148     t.0 = 10;
149     //~^ ERROR assign to part of moved value: `t` [E0382]
150     use_part!(tuple t);
151 }
152
153 fn test_0200_local_void_init_and_use_struct() {
154     let s: S<Void>;
155     s.x = 10;
156     //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
157     use_part!(struct s);
158 }
159
160 fn test_0201_local_void_init_and_use_tuple() {
161     let t: Tvoid;
162     t.0 = 10;
163     //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
164     use_part!(tuple t);
165 }
166
167 // NOTE: uniform structure of tests here makes n21n (aka combining
168 // Void with Reinit) an (even more) senseless case, as we cannot
169 // safely create initial instance containing Void to move out of and
170 // then reinitialize. While I was tempted to sidestep this via some
171 // unsafe code (eek), lets just instead not encode such tests.
172
173 // fn test_0210_local_void_reinit_and_use_struct() { unimplemented!() }
174 // fn test_0211_local_void_reinit_and_use_tuple() { unimplemented!() }
175
176 fn test_1000_field_fully_init_and_use_struct() {
177     let q: Q<S<B>>;
178     q.r.f.x = 10; q.r.f.y = Box::new(20);
179     //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
180     use_fully!(struct q.r.f);
181 }
182
183 fn test_1001_field_fully_init_and_use_tuple() {
184     let q: Q<T>;
185     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
186     //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
187     use_fully!(tuple q.r.f);
188 }
189
190 fn test_1010_field_fully_reinit_and_use_struct() {
191     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
192     q.r.f.x = 10; q.r.f.y = Box::new(20);
193     //~^ ERROR assign to part of moved value: `q.r` [E0382]
194     use_fully!(struct q.r.f);
195 }
196
197 fn test_1011_field_fully_reinit_and_use_tuple() {
198     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
199     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
200     //~^ ERROR assign to part of moved value: `q.r` [E0382]
201     use_fully!(tuple q.r.f);
202 }
203
204 fn test_1100_field_partial_init_and_use_struct() {
205     let q: Q<S<B>>;
206     q.r.f.x = 10;
207     //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
208     use_part!(struct q.r.f);
209 }
210
211 fn test_1101_field_partial_init_and_use_tuple() {
212     let q: Q<T>;
213     q.r.f.0 = 10;
214     //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
215     use_part!(tuple q.r.f);
216 }
217
218 fn test_1110_field_partial_reinit_and_use_struct() {
219     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
220     q.r.f.x = 10;
221     //~^ ERROR assign to part of moved value: `q.r` [E0382]
222     use_part!(struct q.r.f);
223 }
224
225 fn test_1111_field_partial_reinit_and_use_tuple() {
226     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
227     q.r.f.0 = 10;
228     //~^ ERROR assign to part of moved value: `q.r` [E0382]
229     use_part!(tuple q.r.f);
230 }
231
232 fn test_1200_field_void_init_and_use_struct() {
233     let mut q: Q<S<Void>>;
234     q.r.f.x = 10;
235     //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
236     use_part!(struct q.r.f);
237 }
238
239 fn test_1201_field_void_init_and_use_tuple() {
240     let mut q: Q<Tvoid>;
241     q.r.f.0 = 10;
242     //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
243     use_part!(tuple q.r.f);
244 }
245
246 // See NOTE abve.
247
248 // fn test_1210_field_void_reinit_and_use_struct() { unimplemented!() }
249 // fn test_1211_field_void_reinit_and_use_tuple() { unimplemented!() }
250
251 // The below are some additional cases of interest that have been
252 // transcribed from other bugs based on old erroneous codegen when we
253 // encountered partial writes.
254
255 fn issue_26996() {
256     let mut c = (1, "".to_owned());
257     match c {
258         c2 => {
259             c.0 = 2; //~ ERROR assign to part of moved value
260             assert_eq!(c2.0, 1);
261         }
262     }
263 }
264
265 fn issue_27021() {
266     let mut c = (1, (1, "".to_owned()));
267     match c {
268         c2 => {
269             (c.1).0 = 2; //~ ERROR assign to part of moved value
270             assert_eq!((c2.1).0, 1);
271         }
272     }
273
274     let mut c = (1, (1, (1, "".to_owned())));
275     match c.1 {
276         c2 => {
277             ((c.1).1).0 = 3; //~ ERROR assign to part of moved value
278             assert_eq!((c2.1).0, 1);
279         }
280     }
281 }
282
283 fn main() {
284     test_0000_local_fully_init_and_use_struct();
285     test_0001_local_fully_init_and_use_tuple();
286     test_0010_local_fully_reinit_and_use_struct();
287     test_0011_local_fully_reinit_and_use_tuple();
288     test_0100_local_partial_init_and_use_struct();
289     test_0101_local_partial_init_and_use_tuple();
290     test_0110_local_partial_reinit_and_use_struct();
291     test_0111_local_partial_reinit_and_use_tuple();
292     test_0200_local_void_init_and_use_struct();
293     test_0201_local_void_init_and_use_tuple();
294     // test_0210_local_void_reinit_and_use_struct();
295     // test_0211_local_void_reinit_and_use_tuple();
296     test_1000_field_fully_init_and_use_struct();
297     test_1001_field_fully_init_and_use_tuple();
298     test_1010_field_fully_reinit_and_use_struct();
299     test_1011_field_fully_reinit_and_use_tuple();
300     test_1100_field_partial_init_and_use_struct();
301     test_1101_field_partial_init_and_use_tuple();
302     test_1110_field_partial_reinit_and_use_struct();
303     test_1111_field_partial_reinit_and_use_tuple();
304     test_1200_field_void_init_and_use_struct();
305     test_1201_field_void_init_and_use_tuple();
306     // test_1210_field_void_reinit_and_use_struct();
307     // test_1211_field_void_reinit_and_use_tuple();
308
309     issue_26996();
310     issue_27021();
311 }