]> git.proxmox.com Git - rustc.git/blame - src/test/ui/run-pass/rfcs/rfc1857-drop-order.rs
New upstream version 1.30.0+dfsg1
[rustc.git] / src / test / ui / run-pass / rfcs / rfc1857-drop-order.rs
CommitLineData
041b39d2
XL
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.
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
b7449926 11// run-pass
abe05a73
XL
12// ignore-wasm32-bare compiled with panic=abort by default
13
041b39d2
XL
14#![allow(dead_code, unreachable_code)]
15
16use std::cell::RefCell;
17use std::rc::Rc;
18use std::panic::{self, AssertUnwindSafe, UnwindSafe};
19
20// This struct is used to record the order in which elements are dropped
21struct PushOnDrop {
22 vec: Rc<RefCell<Vec<u32>>>,
23 val: u32
24}
25
26impl PushOnDrop {
27 fn new(val: u32, vec: Rc<RefCell<Vec<u32>>>) -> PushOnDrop {
28 PushOnDrop { vec, val }
29 }
30}
31
32impl Drop for PushOnDrop {
33 fn drop(&mut self) {
34 self.vec.borrow_mut().push(self.val)
35 }
36}
37
38impl UnwindSafe for PushOnDrop { }
39
40// Structs
41struct TestStruct {
42 x: PushOnDrop,
43 y: PushOnDrop,
44 z: PushOnDrop
45}
46
47// Tuple structs
48struct TestTupleStruct(PushOnDrop, PushOnDrop, PushOnDrop);
49
50// Enum variants
51enum TestEnum {
52 Tuple(PushOnDrop, PushOnDrop, PushOnDrop),
53 Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop }
54}
55
56fn test_drop_tuple() {
57 // Tuple fields are dropped in the same order they are declared
58 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
59 let test_tuple = (PushOnDrop::new(1, dropped_fields.clone()),
60 PushOnDrop::new(2, dropped_fields.clone()));
61 drop(test_tuple);
62 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
63
64 // Panic during construction means that fields are treated as local variables
65 // Therefore they are dropped in reverse order of initialization
66 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
67 let cloned = AssertUnwindSafe(dropped_fields.clone());
68 panic::catch_unwind(|| {
69 (PushOnDrop::new(2, cloned.clone()),
70 PushOnDrop::new(1, cloned.clone()),
0531ce1d 71 panic!("this panic is caught :D"));
041b39d2
XL
72 }).err().unwrap();
73 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
74}
75
76fn test_drop_struct() {
77 // Struct fields are dropped in the same order they are declared
78 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
79 let test_struct = TestStruct {
80 x: PushOnDrop::new(1, dropped_fields.clone()),
81 y: PushOnDrop::new(2, dropped_fields.clone()),
82 z: PushOnDrop::new(3, dropped_fields.clone()),
83 };
84 drop(test_struct);
85 assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
86
87 // The same holds for tuple structs
88 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
89 let test_tuple_struct = TestTupleStruct(PushOnDrop::new(1, dropped_fields.clone()),
90 PushOnDrop::new(2, dropped_fields.clone()),
91 PushOnDrop::new(3, dropped_fields.clone()));
92 drop(test_tuple_struct);
93 assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
94
95 // Panic during struct construction means that fields are treated as local variables
96 // Therefore they are dropped in reverse order of initialization
97 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
98 let cloned = AssertUnwindSafe(dropped_fields.clone());
99 panic::catch_unwind(|| {
100 TestStruct {
101 x: PushOnDrop::new(2, cloned.clone()),
102 y: PushOnDrop::new(1, cloned.clone()),
0531ce1d 103 z: panic!("this panic is caught :D")
041b39d2
XL
104 };
105 }).err().unwrap();
106 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
107
108 // Test with different initialization order
109 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
110 let cloned = AssertUnwindSafe(dropped_fields.clone());
111 panic::catch_unwind(|| {
112 TestStruct {
113 y: PushOnDrop::new(2, cloned.clone()),
114 x: PushOnDrop::new(1, cloned.clone()),
0531ce1d 115 z: panic!("this panic is caught :D")
041b39d2
XL
116 };
117 }).err().unwrap();
118 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
119
120 // The same holds for tuple structs
121 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
122 let cloned = AssertUnwindSafe(dropped_fields.clone());
123 panic::catch_unwind(|| {
124 TestTupleStruct(PushOnDrop::new(2, cloned.clone()),
125 PushOnDrop::new(1, cloned.clone()),
0531ce1d 126 panic!("this panic is caught :D"));
041b39d2
XL
127 }).err().unwrap();
128 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
129}
130
131fn test_drop_enum() {
132 // Enum variants are dropped in the same order they are declared
133 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
134 let test_struct_enum = TestEnum::Struct {
135 x: PushOnDrop::new(1, dropped_fields.clone()),
136 y: PushOnDrop::new(2, dropped_fields.clone()),
137 z: PushOnDrop::new(3, dropped_fields.clone())
138 };
139 drop(test_struct_enum);
140 assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
141
142 // The same holds for tuple enum variants
143 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
144 let test_tuple_enum = TestEnum::Tuple(PushOnDrop::new(1, dropped_fields.clone()),
145 PushOnDrop::new(2, dropped_fields.clone()),
146 PushOnDrop::new(3, dropped_fields.clone()));
147 drop(test_tuple_enum);
148 assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
149
150 // Panic during enum construction means that fields are treated as local variables
151 // Therefore they are dropped in reverse order of initialization
152 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
153 let cloned = AssertUnwindSafe(dropped_fields.clone());
154 panic::catch_unwind(|| {
155 TestEnum::Struct {
156 x: PushOnDrop::new(2, cloned.clone()),
157 y: PushOnDrop::new(1, cloned.clone()),
0531ce1d 158 z: panic!("this panic is caught :D")
041b39d2
XL
159 };
160 }).err().unwrap();
161 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
162
163 // Test with different initialization order
164 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
165 let cloned = AssertUnwindSafe(dropped_fields.clone());
166 panic::catch_unwind(|| {
167 TestEnum::Struct {
168 y: PushOnDrop::new(2, cloned.clone()),
169 x: PushOnDrop::new(1, cloned.clone()),
0531ce1d 170 z: panic!("this panic is caught :D")
041b39d2
XL
171 };
172 }).err().unwrap();
173 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
174
175 // The same holds for tuple enum variants
176 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
177 let cloned = AssertUnwindSafe(dropped_fields.clone());
178 panic::catch_unwind(|| {
179 TestEnum::Tuple(PushOnDrop::new(2, cloned.clone()),
180 PushOnDrop::new(1, cloned.clone()),
0531ce1d 181 panic!("this panic is caught :D"));
041b39d2
XL
182 }).err().unwrap();
183 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
184}
185
186fn test_drop_list() {
187 // Elements in a Vec are dropped in the same order they are pushed
188 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
189 let xs = vec![PushOnDrop::new(1, dropped_fields.clone()),
190 PushOnDrop::new(2, dropped_fields.clone()),
191 PushOnDrop::new(3, dropped_fields.clone())];
192 drop(xs);
193 assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
194
195 // The same holds for arrays
196 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
197 let xs = [PushOnDrop::new(1, dropped_fields.clone()),
198 PushOnDrop::new(2, dropped_fields.clone()),
199 PushOnDrop::new(3, dropped_fields.clone())];
200 drop(xs);
201 assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
202
203 // Panic during vec construction means that fields are treated as local variables
204 // Therefore they are dropped in reverse order of initialization
205 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
206 let cloned = AssertUnwindSafe(dropped_fields.clone());
207 panic::catch_unwind(|| {
208 vec![
209 PushOnDrop::new(2, cloned.clone()),
210 PushOnDrop::new(1, cloned.clone()),
0531ce1d 211 panic!("this panic is caught :D")
041b39d2
XL
212 ];
213 }).err().unwrap();
214 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
215
216 // The same holds for arrays
217 let dropped_fields = Rc::new(RefCell::new(Vec::new()));
218 let cloned = AssertUnwindSafe(dropped_fields.clone());
219 panic::catch_unwind(|| {
220 [
221 PushOnDrop::new(2, cloned.clone()),
222 PushOnDrop::new(1, cloned.clone()),
0531ce1d 223 panic!("this panic is caught :D")
041b39d2
XL
224 ];
225 }).err().unwrap();
226 assert_eq!(*dropped_fields.borrow(), &[1, 2]);
227}
228
229fn main() {
230 test_drop_tuple();
231 test_drop_struct();
232 test_drop_enum();
233 test_drop_list();
234}