]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/drop/dynamic-drop.rs
Rollup merge of #54567 - tromey:paths-in-stamp-hashes, r=Mark-Simulacrum
[rust.git] / src / test / run-pass / drop / dynamic-drop.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // run-pass
12 #![allow(unused_assignments)]
13 #![allow(unused_variables)]
14 // revisions:lexical nll
15 #![cfg_attr(nll, feature(nll))]
16
17 // ignore-wasm32-bare compiled with panic=abort by default
18
19 #![feature(generators, generator_trait, untagged_unions)]
20 #![feature(slice_patterns)]
21
22 use std::cell::{Cell, RefCell};
23 use std::ops::Generator;
24 use std::panic;
25 use std::usize;
26
27 struct InjectedFailure;
28
29 struct Allocator {
30     data: RefCell<Vec<bool>>,
31     failing_op: usize,
32     cur_ops: Cell<usize>,
33 }
34
35 impl panic::UnwindSafe for Allocator {}
36 impl panic::RefUnwindSafe for Allocator {}
37
38 impl Drop for Allocator {
39     fn drop(&mut self) {
40         let data = self.data.borrow();
41         if data.iter().any(|d| *d) {
42             panic!("missing free: {:?}", data);
43         }
44     }
45 }
46
47 impl Allocator {
48     fn new(failing_op: usize) -> Self {
49         Allocator {
50             failing_op: failing_op,
51             cur_ops: Cell::new(0),
52             data: RefCell::new(vec![])
53         }
54     }
55     fn alloc(&self) -> Ptr {
56         self.cur_ops.set(self.cur_ops.get() + 1);
57
58         if self.cur_ops.get() == self.failing_op {
59             panic!(InjectedFailure);
60         }
61
62         let mut data = self.data.borrow_mut();
63         let addr = data.len();
64         data.push(true);
65         Ptr(addr, self)
66     }
67 }
68
69 struct Ptr<'a>(usize, &'a Allocator);
70 impl<'a> Drop for Ptr<'a> {
71     fn drop(&mut self) {
72         match self.1.data.borrow_mut()[self.0] {
73             false => {
74                 panic!("double free at index {:?}", self.0)
75             }
76             ref mut d => *d = false
77         }
78
79         self.1.cur_ops.set(self.1.cur_ops.get()+1);
80
81         if self.1.cur_ops.get() == self.1.failing_op {
82             panic!(InjectedFailure);
83         }
84     }
85 }
86
87 fn dynamic_init(a: &Allocator, c: bool) {
88     let _x;
89     if c {
90         _x = Some(a.alloc());
91     }
92 }
93
94 fn dynamic_drop(a: &Allocator, c: bool) {
95     let x = a.alloc();
96     if c {
97         Some(x)
98     } else {
99         None
100     };
101 }
102
103 struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>);
104 fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) {
105     for i in 0..2 {
106         let x;
107         let y;
108         if (c0 && i == 0) || (c1 && i == 1) {
109             x = (a.alloc(), a.alloc(), a.alloc());
110             y = TwoPtrs(a.alloc(), a.alloc());
111             if c {
112                 drop(x.1);
113                 drop(y.0);
114             }
115         }
116     }
117 }
118
119 fn field_assignment(a: &Allocator, c0: bool) {
120     let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc());
121
122     x.1 = a.alloc();
123     x.1 = a.alloc();
124
125     let f = (x.0).0;
126     if c0 {
127         (x.0).0 = f;
128     }
129 }
130
131 fn assignment2(a: &Allocator, c0: bool, c1: bool) {
132     let mut _v = a.alloc();
133     let mut _w = a.alloc();
134     if c0 {
135         drop(_v);
136     }
137     _v = _w;
138     if c1 {
139         _w = a.alloc();
140     }
141 }
142
143 fn assignment1(a: &Allocator, c0: bool) {
144     let mut _v = a.alloc();
145     let mut _w = a.alloc();
146     if c0 {
147         drop(_v);
148     }
149     _v = _w;
150 }
151
152 #[allow(unions_with_drop_fields)]
153 union Boxy<T> {
154     a: T,
155     b: T,
156 }
157
158 fn union1(a: &Allocator) {
159     unsafe {
160         let mut u = Boxy { a: a.alloc() };
161         u.b = a.alloc();
162         drop(u.a);
163     }
164 }
165
166 fn array_simple(a: &Allocator) {
167     let _x = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
168 }
169
170 fn vec_simple(a: &Allocator) {
171     let _x = vec![a.alloc(), a.alloc(), a.alloc(), a.alloc()];
172 }
173
174 fn generator(a: &Allocator, run_count: usize) {
175     assert!(run_count < 4);
176
177     let mut gen = || {
178         (a.alloc(),
179          yield a.alloc(),
180          a.alloc(),
181          yield a.alloc()
182          );
183     };
184     for _ in 0..run_count {
185         unsafe { gen.resume(); }
186     }
187 }
188
189 fn mixed_drop_and_nondrop(a: &Allocator) {
190     // check that destructor panics handle drop
191     // and non-drop blocks in the same scope correctly.
192     //
193     // Surprisingly enough, this used to not work.
194     let (x, y, z);
195     x = a.alloc();
196     y = 5;
197     z = a.alloc();
198 }
199
200 #[allow(unreachable_code)]
201 fn vec_unreachable(a: &Allocator) {
202     let _x = vec![a.alloc(), a.alloc(), a.alloc(), return];
203 }
204
205 fn slice_pattern_first(a: &Allocator) {
206     let[_x, ..] = [a.alloc(), a.alloc(), a.alloc()];
207 }
208
209 fn slice_pattern_middle(a: &Allocator) {
210     let[_, _x, _] = [a.alloc(), a.alloc(), a.alloc()];
211 }
212
213 fn slice_pattern_two(a: &Allocator) {
214     let[_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
215 }
216
217 fn slice_pattern_last(a: &Allocator) {
218     let[.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
219 }
220
221 fn slice_pattern_one_of(a: &Allocator, i: usize) {
222     let array = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
223     let _x = match i {
224         0 => { let [a, ..] = array; a }
225         1 => { let [_, a, ..] = array; a }
226         2 => { let [_, _, a, _] = array; a }
227         3 => { let [_, _, _, a] = array; a }
228         _ => panic!("unmatched"),
229     };
230 }
231
232 fn subslice_pattern_from_end(a: &Allocator, arg: bool) {
233     let a = [a.alloc(), a.alloc(), a.alloc()];
234     if arg {
235         let[.., _x, _] = a;
236     } else {
237         let[_, _y..] = a;
238     }
239 }
240
241 fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) {
242     let a = [a.alloc(), a.alloc(), a.alloc(), a.alloc(), a.alloc()];
243     if arg2 {
244         drop(a);
245         return;
246     }
247
248     if arg {
249         let[.., _x, _] = a;
250     } else {
251         let[_, _y..] = a;
252     }
253 }
254
255 fn slice_pattern_reassign(a: &Allocator) {
256     let mut ar = [a.alloc(), a.alloc()];
257     let[_, _x] = ar;
258     ar = [a.alloc(), a.alloc()];
259     let[.., _y] = ar;
260 }
261
262 fn subslice_pattern_reassign(a: &Allocator) {
263     let mut ar = [a.alloc(), a.alloc(), a.alloc()];
264     let[_, _, _x] = ar;
265     ar = [a.alloc(), a.alloc(), a.alloc()];
266     let[_, _y..] = ar;
267 }
268
269 fn run_test<F>(mut f: F)
270     where F: FnMut(&Allocator)
271 {
272     let first_alloc = Allocator::new(usize::MAX);
273     f(&first_alloc);
274
275     for failing_op in 1..first_alloc.cur_ops.get()+1 {
276         let alloc = Allocator::new(failing_op);
277         let alloc = &alloc;
278         let f = panic::AssertUnwindSafe(&mut f);
279         let result = panic::catch_unwind(move || {
280             f.0(alloc);
281         });
282         match result {
283             Ok(..) => panic!("test executed {} ops but now {}",
284                              first_alloc.cur_ops.get(), alloc.cur_ops.get()),
285             Err(e) => {
286                 if e.downcast_ref::<InjectedFailure>().is_none() {
287                     panic::resume_unwind(e);
288                 }
289             }
290         }
291     }
292 }
293
294 fn run_test_nopanic<F>(mut f: F)
295     where F: FnMut(&Allocator)
296 {
297     let first_alloc = Allocator::new(usize::MAX);
298     f(&first_alloc);
299 }
300
301 fn main() {
302     run_test(|a| dynamic_init(a, false));
303     run_test(|a| dynamic_init(a, true));
304     run_test(|a| dynamic_drop(a, false));
305     run_test(|a| dynamic_drop(a, true));
306
307     run_test(|a| assignment2(a, false, false));
308     run_test(|a| assignment2(a, false, true));
309     run_test(|a| assignment2(a, true, false));
310     run_test(|a| assignment2(a, true, true));
311
312     run_test(|a| assignment1(a, false));
313     run_test(|a| assignment1(a, true));
314
315     run_test(|a| array_simple(a));
316     run_test(|a| vec_simple(a));
317     run_test(|a| vec_unreachable(a));
318
319     run_test(|a| struct_dynamic_drop(a, false, false, false));
320     run_test(|a| struct_dynamic_drop(a, false, false, true));
321     run_test(|a| struct_dynamic_drop(a, false, true, false));
322     run_test(|a| struct_dynamic_drop(a, false, true, true));
323     run_test(|a| struct_dynamic_drop(a, true, false, false));
324     run_test(|a| struct_dynamic_drop(a, true, false, true));
325     run_test(|a| struct_dynamic_drop(a, true, true, false));
326     run_test(|a| struct_dynamic_drop(a, true, true, true));
327
328     run_test(|a| field_assignment(a, false));
329     run_test(|a| field_assignment(a, true));
330
331     run_test(|a| generator(a, 0));
332     run_test(|a| generator(a, 1));
333     run_test(|a| generator(a, 2));
334     run_test(|a| generator(a, 3));
335
336     run_test(|a| mixed_drop_and_nondrop(a));
337
338     run_test(|a| slice_pattern_first(a));
339     run_test(|a| slice_pattern_middle(a));
340     run_test(|a| slice_pattern_two(a));
341     run_test(|a| slice_pattern_last(a));
342     run_test(|a| slice_pattern_one_of(a, 0));
343     run_test(|a| slice_pattern_one_of(a, 1));
344     run_test(|a| slice_pattern_one_of(a, 2));
345     run_test(|a| slice_pattern_one_of(a, 3));
346
347     run_test(|a| subslice_pattern_from_end(a, true));
348     run_test(|a| subslice_pattern_from_end(a, false));
349     run_test(|a| subslice_pattern_from_end_with_drop(a, true, true));
350     run_test(|a| subslice_pattern_from_end_with_drop(a, true, false));
351     run_test(|a| subslice_pattern_from_end_with_drop(a, false, true));
352     run_test(|a| subslice_pattern_from_end_with_drop(a, false, false));
353     run_test(|a| slice_pattern_reassign(a));
354     run_test(|a| subslice_pattern_reassign(a));
355
356     run_test_nopanic(|a| union1(a));
357 }