1 // This test enumerates various cases of interest for partial
2 // [re]initialization of ADTs and tuples.
4 // See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987.
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.)
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.
18 // Note that even though `y` may implement `Drop`, under #54987 we
19 // will still allow partial initialization of `S` itself.
27 impl S<B> { fn new() -> Self { S { x: 0, y: Box::new(0) } } }
29 fn borrow_s(s: &S<B>) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
30 fn move_s(s: S<B>) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
31 fn borrow_field(x: &u32) { assert_eq!(*x, 10); }
34 type Tvoid = (u32, Void);
36 fn borrow_t(t: &T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
37 fn move_t(t: T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
49 impl<F> Q<F> { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } }
50 impl<F> R<F> { fn new(f: F) -> Self { R { w: 0, f } } }
53 // * local/field: Is the structure in a local or a field
54 // * fully/partial/void: Are we fully initializing it before using any part?
55 // Is whole type empty due to a void component?
56 // * init/reinit: First initialization, or did we previously inititalize and then move out?
57 // * struct/tuple: Is this a struct or a (X, Y).
59 // As a shorthand for the cases above, adding a numeric summary to
60 // each test's fn name to denote each point on each axis.
62 // e.g., 1000 = field fully init struct; 0211 = local void reinit tuple
64 // It got pretty monotonous writing the same code over and over, and I
65 // feared I would forget details. So I abstracted some desiderata into
66 // macros. But I left the initialization code inline, because that's
67 // where the errors for #54986 will be emitted.
69 macro_rules! use_fully {
70 (struct $s:expr) => { {
71 borrow_field(& $s.x );
76 (tuple $t:expr) => { {
77 borrow_field(& $t.0 );
83 macro_rules! use_part {
84 (struct $s:expr) => { {
85 borrow_field(& $s.x );
86 match $s { S { ref x, y: _ } => { borrow_field(x); } }
89 (tuple $t:expr) => { {
90 borrow_field(& $t.0 );
91 match $t { (ref x, _) => { borrow_field(x); } }
95 fn test_0000_local_fully_init_and_use_struct() {
97 s.x = 10; s.y = Box::new(20);
98 //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
102 fn test_0001_local_fully_init_and_use_tuple() {
104 t.0 = 10; t.1 = Box::new(20);
105 //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
109 fn test_0010_local_fully_reinit_and_use_struct() {
110 let mut s: S<B> = S::new(); drop(s);
111 s.x = 10; s.y = Box::new(20);
112 //~^ ERROR assign to part of moved value: `s` [E0382]
113 use_fully!(struct s);
116 fn test_0011_local_fully_reinit_and_use_tuple() {
117 let mut t: T = (0, Box::new(0)); drop(t);
118 t.0 = 10; t.1 = Box::new(20);
119 //~^ ERROR assign to part of moved value: `t` [E0382]
123 fn test_0100_local_partial_init_and_use_struct() {
126 //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
130 fn test_0101_local_partial_init_and_use_tuple() {
133 //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
137 fn test_0110_local_partial_reinit_and_use_struct() {
138 let mut s: S<B> = S::new(); drop(s);
140 //~^ ERROR assign to part of moved value: `s` [E0382]
144 fn test_0111_local_partial_reinit_and_use_tuple() {
145 let mut t: T = (0, Box::new(0)); drop(t);
147 //~^ ERROR assign to part of moved value: `t` [E0382]
151 fn test_0200_local_void_init_and_use_struct() {
154 //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
158 fn test_0201_local_void_init_and_use_tuple() {
161 //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
165 // NOTE: uniform structure of tests here makes n21n (aka combining
166 // Void with Reinit) an (even more) senseless case, as we cannot
167 // safely create initial instance containing Void to move out of and
168 // then reinitialize. While I was tempted to sidestep this via some
169 // unsafe code (eek), lets just instead not encode such tests.
171 // fn test_0210_local_void_reinit_and_use_struct() { unimplemented!() }
172 // fn test_0211_local_void_reinit_and_use_tuple() { unimplemented!() }
174 fn test_1000_field_fully_init_and_use_struct() {
176 q.r.f.x = 10; q.r.f.y = Box::new(20);
177 //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
178 use_fully!(struct q.r.f);
181 fn test_1001_field_fully_init_and_use_tuple() {
183 q.r.f.0 = 10; q.r.f.1 = Box::new(20);
184 //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
185 use_fully!(tuple q.r.f);
188 fn test_1010_field_fully_reinit_and_use_struct() {
189 let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
190 q.r.f.x = 10; q.r.f.y = Box::new(20);
191 //~^ ERROR assign to part of moved value: `q.r` [E0382]
192 use_fully!(struct q.r.f);
195 fn test_1011_field_fully_reinit_and_use_tuple() {
196 let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
197 q.r.f.0 = 10; q.r.f.1 = Box::new(20);
198 //~^ ERROR assign to part of moved value: `q.r` [E0382]
199 use_fully!(tuple q.r.f);
202 fn test_1100_field_partial_init_and_use_struct() {
205 //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
206 use_part!(struct q.r.f);
209 fn test_1101_field_partial_init_and_use_tuple() {
212 //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
213 use_part!(tuple q.r.f);
216 fn test_1110_field_partial_reinit_and_use_struct() {
217 let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
219 //~^ ERROR assign to part of moved value: `q.r` [E0382]
220 use_part!(struct q.r.f);
223 fn test_1111_field_partial_reinit_and_use_tuple() {
224 let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
226 //~^ ERROR assign to part of moved value: `q.r` [E0382]
227 use_part!(tuple q.r.f);
230 fn test_1200_field_void_init_and_use_struct() {
231 let mut q: Q<S<Void>>;
233 //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
234 use_part!(struct q.r.f);
237 fn test_1201_field_void_init_and_use_tuple() {
240 //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
241 use_part!(tuple q.r.f);
246 // fn test_1210_field_void_reinit_and_use_struct() { unimplemented!() }
247 // fn test_1211_field_void_reinit_and_use_tuple() { unimplemented!() }
249 // The below are some additional cases of interest that have been
250 // transcribed from other bugs based on old erroneous codegen when we
251 // encountered partial writes.
254 let mut c = (1, "".to_owned());
257 c.0 = 2; //~ ERROR assign to part of moved value
264 let mut c = (1, (1, "".to_owned()));
267 (c.1).0 = 2; //~ ERROR assign to part of moved value
268 assert_eq!((c2.1).0, 1);
272 let mut c = (1, (1, (1, "".to_owned())));
275 ((c.1).1).0 = 3; //~ ERROR assign to part of moved value
276 assert_eq!((c2.1).0, 1);
282 test_0000_local_fully_init_and_use_struct();
283 test_0001_local_fully_init_and_use_tuple();
284 test_0010_local_fully_reinit_and_use_struct();
285 test_0011_local_fully_reinit_and_use_tuple();
286 test_0100_local_partial_init_and_use_struct();
287 test_0101_local_partial_init_and_use_tuple();
288 test_0110_local_partial_reinit_and_use_struct();
289 test_0111_local_partial_reinit_and_use_tuple();
290 test_0200_local_void_init_and_use_struct();
291 test_0201_local_void_init_and_use_tuple();
292 // test_0210_local_void_reinit_and_use_struct();
293 // test_0211_local_void_reinit_and_use_tuple();
294 test_1000_field_fully_init_and_use_struct();
295 test_1001_field_fully_init_and_use_tuple();
296 test_1010_field_fully_reinit_and_use_struct();
297 test_1011_field_fully_reinit_and_use_tuple();
298 test_1100_field_partial_init_and_use_struct();
299 test_1101_field_partial_init_and_use_tuple();
300 test_1110_field_partial_reinit_and_use_struct();
301 test_1111_field_partial_reinit_and_use_tuple();
302 test_1200_field_void_init_and_use_struct();
303 test_1201_field_void_init_and_use_tuple();
304 // test_1210_field_void_reinit_and_use_struct();
305 // test_1211_field_void_reinit_and_use_tuple();