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.
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.
11 // revisions:lexical nll
12 #![cfg_attr(nll, feature(nll))]
14 // ignore-wasm32-bare compiled with panic=abort by default
16 #![feature(generators, generator_trait, untagged_unions)]
17 #![feature(slice_patterns)]
19 use std
::cell
::{Cell, RefCell}
;
20 use std
::ops
::Generator
;
24 struct InjectedFailure
;
27 data
: RefCell
<Vec
<bool
>>,
32 impl panic
::UnwindSafe
for Allocator {}
33 impl panic
::RefUnwindSafe
for Allocator {}
35 impl Drop
for Allocator
{
37 let data
= self.data
.borrow();
38 if data
.iter().any(|d
| *d
) {
39 panic
!("missing free: {:?}", data
);
45 fn new(failing_op
: usize) -> Self {
47 failing_op
: failing_op
,
48 cur_ops
: Cell
::new(0),
49 data
: RefCell
::new(vec
![])
52 fn alloc(&self) -> Ptr
{
53 self.cur_ops
.set(self.cur_ops
.get() + 1);
55 if self.cur_ops
.get() == self.failing_op
{
56 panic
!(InjectedFailure
);
59 let mut data
= self.data
.borrow_mut();
60 let addr
= data
.len();
66 struct Ptr
<'a
>(usize, &'a Allocator
);
67 impl<'a
> Drop
for Ptr
<'a
> {
69 match self.1.data
.borrow_mut()[self.0] {
71 panic
!("double free at index {:?}", self.0)
73 ref mut d
=> *d
= false
76 self.1.cur_ops
.set(self.1.cur_ops
.get()+1);
78 if self.1.cur_ops
.get() == self.1.failing_op
{
79 panic
!(InjectedFailure
);
84 fn dynamic_init(a
: &Allocator
, c
: bool
) {
91 fn dynamic_drop(a
: &Allocator
, c
: bool
) {
100 struct TwoPtrs
<'a
>(Ptr
<'a
>, Ptr
<'a
>);
101 fn struct_dynamic_drop(a
: &Allocator
, c0
: bool
, c1
: bool
, c
: bool
) {
105 if (c0
&& i
== 0) || (c1
&& i
== 1) {
106 x
= (a
.alloc(), a
.alloc(), a
.alloc());
107 y
= TwoPtrs(a
.alloc(), a
.alloc());
116 fn field_assignment(a
: &Allocator
, c0
: bool
) {
117 let mut x
= (TwoPtrs(a
.alloc(), a
.alloc()), a
.alloc());
128 fn assignment2(a
: &Allocator
, c0
: bool
, c1
: bool
) {
129 let mut _v
= a
.alloc();
130 let mut _w
= a
.alloc();
140 fn assignment1(a
: &Allocator
, c0
: bool
) {
141 let mut _v
= a
.alloc();
142 let mut _w
= a
.alloc();
149 #[allow(unions_with_drop_fields)]
155 fn union1(a
: &Allocator
) {
157 let mut u
= Boxy { a: a.alloc() }
;
163 fn array_simple(a
: &Allocator
) {
164 let _x
= [a
.alloc(), a
.alloc(), a
.alloc(), a
.alloc()];
167 fn vec_simple(a
: &Allocator
) {
168 let _x
= vec
![a
.alloc(), a
.alloc(), a
.alloc(), a
.alloc()];
171 fn generator(a
: &Allocator
, run_count
: usize) {
172 assert
!(run_count
< 4);
181 for _
in 0..run_count
{
182 unsafe { gen.resume(); }
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.
190 // Surprisingly enough, this used to not work.
197 #[allow(unreachable_code)]
198 fn vec_unreachable(a
: &Allocator
) {
199 let _x
= vec
![a
.alloc(), a
.alloc(), a
.alloc(), return];
202 fn slice_pattern_first(a
: &Allocator
) {
203 let[_x
, ..] = [a
.alloc(), a
.alloc(), a
.alloc()];
206 fn slice_pattern_middle(a
: &Allocator
) {
207 let[_
, _x
, _
] = [a
.alloc(), a
.alloc(), a
.alloc()];
210 fn slice_pattern_two(a
: &Allocator
) {
211 let[_x
, _
, _y
, _
] = [a
.alloc(), a
.alloc(), a
.alloc(), a
.alloc()];
214 fn slice_pattern_last(a
: &Allocator
) {
215 let[.., _y
] = [a
.alloc(), a
.alloc(), a
.alloc(), a
.alloc()];
218 fn slice_pattern_one_of(a
: &Allocator
, i
: usize) {
219 let array
= [a
.alloc(), a
.alloc(), a
.alloc(), a
.alloc()];
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"),
229 fn subslice_pattern_from_end(a
: &Allocator
, arg
: bool
) {
230 let a
= [a
.alloc(), a
.alloc(), a
.alloc()];
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()];
252 fn slice_pattern_reassign(a
: &Allocator
) {
253 let mut ar
= [a
.alloc(), a
.alloc()];
255 ar
= [a
.alloc(), a
.alloc()];
259 fn subslice_pattern_reassign(a
: &Allocator
) {
260 let mut ar
= [a
.alloc(), a
.alloc(), a
.alloc()];
262 ar
= [a
.alloc(), a
.alloc(), a
.alloc()];
266 fn run_test
<F
>(mut f
: F
)
267 where F
: FnMut(&Allocator
)
269 let first_alloc
= Allocator
::new(usize::MAX
);
272 for failing_op
in 1..first_alloc
.cur_ops
.get()+1 {
273 let alloc
= Allocator
::new(failing_op
);
275 let f
= panic
::AssertUnwindSafe(&mut f
);
276 let result
= panic
::catch_unwind(move || {
280 Ok(..) => panic
!("test executed {} ops but now {}",
281 first_alloc
.cur_ops
.get(), alloc
.cur_ops
.get()),
283 if e
.downcast_ref
::<InjectedFailure
>().is_none() {
284 panic
::resume_unwind(e
);
291 fn run_test_nopanic
<F
>(mut f
: F
)
292 where F
: FnMut(&Allocator
)
294 let first_alloc
= Allocator
::new(usize::MAX
);
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));
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));
309 run_test(|a
| assignment1(a
, false));
310 run_test(|a
| assignment1(a
, true));
312 run_test(|a
| array_simple(a
));
313 run_test(|a
| vec_simple(a
));
314 run_test(|a
| vec_unreachable(a
));
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));
325 run_test(|a
| field_assignment(a
, false));
326 run_test(|a
| field_assignment(a
, true));
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));
333 run_test(|a
| mixed_drop_and_nondrop(a
));
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));
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
));
353 run_test_nopanic(|a
| union1(a
));