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