1 // Copyright 2017 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 // ignore-wasm32-bare compiled with panic=abort by default
13 #![allow(dead_code, unreachable_code)]
15 use std
::cell
::RefCell
;
17 use std
::panic
::{self, AssertUnwindSafe, UnwindSafe}
;
19 // This struct is used to record the order in which elements are dropped
21 vec
: Rc
<RefCell
<Vec
<u32>>>,
26 fn new(val
: u32, vec
: Rc
<RefCell
<Vec
<u32>>>) -> PushOnDrop
{
27 PushOnDrop { vec, val }
31 impl Drop
for PushOnDrop
{
33 self.vec
.borrow_mut().push(self.val
)
37 impl UnwindSafe
for PushOnDrop { }
47 struct TestTupleStruct(PushOnDrop
, PushOnDrop
, PushOnDrop
);
51 Tuple(PushOnDrop
, PushOnDrop
, PushOnDrop
),
52 Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop }
55 fn test_drop_tuple() {
56 // Tuple fields are dropped in the same order they are declared
57 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
58 let test_tuple
= (PushOnDrop
::new(1, dropped_fields
.clone()),
59 PushOnDrop
::new(2, dropped_fields
.clone()));
61 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
63 // Panic during construction means that fields are treated as local variables
64 // Therefore they are dropped in reverse order of initialization
65 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
66 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
67 panic
::catch_unwind(|| {
68 (PushOnDrop
::new(2, cloned
.clone()),
69 PushOnDrop
::new(1, cloned
.clone()),
70 panic
!("this panic is catched :D"));
72 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
75 fn test_drop_struct() {
76 // Struct fields are dropped in the same order they are declared
77 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
78 let test_struct
= TestStruct
{
79 x
: PushOnDrop
::new(1, dropped_fields
.clone()),
80 y
: PushOnDrop
::new(2, dropped_fields
.clone()),
81 z
: PushOnDrop
::new(3, dropped_fields
.clone()),
84 assert_eq
!(*dropped_fields
.borrow(), &[1, 2, 3]);
86 // The same holds for tuple structs
87 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
88 let test_tuple_struct
= TestTupleStruct(PushOnDrop
::new(1, dropped_fields
.clone()),
89 PushOnDrop
::new(2, dropped_fields
.clone()),
90 PushOnDrop
::new(3, dropped_fields
.clone()));
91 drop(test_tuple_struct
);
92 assert_eq
!(*dropped_fields
.borrow(), &[1, 2, 3]);
94 // Panic during struct construction means that fields are treated as local variables
95 // Therefore they are dropped in reverse order of initialization
96 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
97 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
98 panic
::catch_unwind(|| {
100 x
: PushOnDrop
::new(2, cloned
.clone()),
101 y
: PushOnDrop
::new(1, cloned
.clone()),
102 z
: panic
!("this panic is catched :D")
105 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
107 // Test with different initialization order
108 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
109 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
110 panic
::catch_unwind(|| {
112 y
: PushOnDrop
::new(2, cloned
.clone()),
113 x
: PushOnDrop
::new(1, cloned
.clone()),
114 z
: panic
!("this panic is catched :D")
117 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
119 // The same holds for tuple structs
120 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
121 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
122 panic
::catch_unwind(|| {
123 TestTupleStruct(PushOnDrop
::new(2, cloned
.clone()),
124 PushOnDrop
::new(1, cloned
.clone()),
125 panic
!("this panic is catched :D"));
127 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
130 fn test_drop_enum() {
131 // Enum variants are dropped in the same order they are declared
132 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
133 let test_struct_enum
= TestEnum
::Struct
{
134 x
: PushOnDrop
::new(1, dropped_fields
.clone()),
135 y
: PushOnDrop
::new(2, dropped_fields
.clone()),
136 z
: PushOnDrop
::new(3, dropped_fields
.clone())
138 drop(test_struct_enum
);
139 assert_eq
!(*dropped_fields
.borrow(), &[1, 2, 3]);
141 // The same holds for tuple enum variants
142 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
143 let test_tuple_enum
= TestEnum
::Tuple(PushOnDrop
::new(1, dropped_fields
.clone()),
144 PushOnDrop
::new(2, dropped_fields
.clone()),
145 PushOnDrop
::new(3, dropped_fields
.clone()));
146 drop(test_tuple_enum
);
147 assert_eq
!(*dropped_fields
.borrow(), &[1, 2, 3]);
149 // Panic during enum construction means that fields are treated as local variables
150 // Therefore they are dropped in reverse order of initialization
151 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
152 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
153 panic
::catch_unwind(|| {
155 x
: PushOnDrop
::new(2, cloned
.clone()),
156 y
: PushOnDrop
::new(1, cloned
.clone()),
157 z
: panic
!("this panic is catched :D")
160 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
162 // Test with different initialization order
163 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
164 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
165 panic
::catch_unwind(|| {
167 y
: PushOnDrop
::new(2, cloned
.clone()),
168 x
: PushOnDrop
::new(1, cloned
.clone()),
169 z
: panic
!("this panic is catched :D")
172 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
174 // The same holds for tuple enum variants
175 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
176 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
177 panic
::catch_unwind(|| {
178 TestEnum
::Tuple(PushOnDrop
::new(2, cloned
.clone()),
179 PushOnDrop
::new(1, cloned
.clone()),
180 panic
!("this panic is catched :D"));
182 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
185 fn test_drop_list() {
186 // Elements in a Vec are dropped in the same order they are pushed
187 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
188 let xs
= vec
![PushOnDrop
::new(1, dropped_fields
.clone()),
189 PushOnDrop
::new(2, dropped_fields
.clone()),
190 PushOnDrop
::new(3, dropped_fields
.clone())];
192 assert_eq
!(*dropped_fields
.borrow(), &[1, 2, 3]);
194 // The same holds for arrays
195 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
196 let xs
= [PushOnDrop
::new(1, dropped_fields
.clone()),
197 PushOnDrop
::new(2, dropped_fields
.clone()),
198 PushOnDrop
::new(3, dropped_fields
.clone())];
200 assert_eq
!(*dropped_fields
.borrow(), &[1, 2, 3]);
202 // Panic during vec construction means that fields are treated as local variables
203 // Therefore they are dropped in reverse order of initialization
204 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
205 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
206 panic
::catch_unwind(|| {
208 PushOnDrop
::new(2, cloned
.clone()),
209 PushOnDrop
::new(1, cloned
.clone()),
210 panic
!("this panic is catched :D")
213 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);
215 // The same holds for arrays
216 let dropped_fields
= Rc
::new(RefCell
::new(Vec
::new()));
217 let cloned
= AssertUnwindSafe(dropped_fields
.clone());
218 panic
::catch_unwind(|| {
220 PushOnDrop
::new(2, cloned
.clone()),
221 PushOnDrop
::new(1, cloned
.clone()),
222 panic
!("this panic is catched :D")
225 assert_eq
!(*dropped_fields
.borrow(), &[1, 2]);