]> git.proxmox.com Git - rustc.git/blob - src/test/run-pass/issue-23338-ensure-param-drop-order.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / test / run-pass / issue-23338-ensure-param-drop-order.rs
1 // Copyright 2015 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 #![feature(rustc_attrs)]
12
13 // ignore-pretty : (#23623) problems when ending with // comments
14
15 // This test is ensuring that parameters are indeed dropped after
16 // temporaries in a fn body.
17
18 use std::cell::RefCell;
19
20 use self::d::D;
21
22 pub fn main() {
23 let log = RefCell::new(vec![]);
24 d::println("created empty log");
25 test(&log);
26
27 assert_eq!(&log.borrow()[..],
28 [
29 // created empty log
30 // +-- Make D(da_0, 0)
31 // | +-- Make D(de_1, 1)
32 // | | calling foo
33 // | | entered foo
34 // | | +-- Make D(de_2, 2)
35 // | | | +-- Make D(da_1, 3)
36 // | | | | +-- Make D(de_3, 4)
37 // | | | | | +-- Make D(de_4, 5)
38 3, // | | | +-- Drop D(da_1, 3)
39 // | | | | |
40 4, // | | | +-- Drop D(de_3, 4)
41 // | | | |
42 // | | | | eval tail of foo
43 // | | | +-- Make D(de_5, 6)
44 // | | | | +-- Make D(de_6, 7)
45 6, // | | | +-- Drop D(de_5, 6)
46 // | | | | |
47 5, // | | | | +-- Drop D(de_4, 5)
48 // | | | |
49 2, // | | +-- Drop D(de_2, 2)
50 // | | |
51 1, // | +-- Drop D(de_1, 1)
52 // | |
53 0, // +-- Drop D(da_0, 0)
54 // |
55 // | result D(de_6, 7)
56 7 // +-- Drop D(de_6, 7)
57
58 ]);
59 }
60
61 fn test<'a>(log: d::Log<'a>) {
62 let da = D::new("da", 0, log);
63 let de = D::new("de", 1, log);
64 d::println("calling foo");
65 let result = foo(da, de);
66 d::println(&format!("result {}", result));
67 }
68
69 #[rustc_no_mir] // FIXME #29855 MIR doesn't handle all drops correctly.
70 fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> {
71 d::println("entered foo");
72 let de2 = de1.incr(); // creates D(de_2, 2)
73 let de4 = {
74 let _da1 = da0.incr(); // creates D(da_1, 3)
75 de2.incr().incr() // creates D(de_3, 4) and D(de_4, 5)
76 };
77 d::println("eval tail of foo");
78 de4.incr().incr() // creates D(de_5, 6) and D(de_6, 7)
79 }
80
81 // This module provides simultaneous printouts of the dynamic extents
82 // of all of the D values, in addition to logging the order that each
83 // is dropped.
84
85 const PREF_INDENT: u32 = 16;
86
87 pub mod d {
88 #![allow(unused_parens)]
89 use std::fmt;
90 use std::mem;
91 use std::cell::RefCell;
92
93 static mut counter: u32 = 0;
94 static mut trails: u64 = 0;
95
96 pub type Log<'a> = &'a RefCell<Vec<u32>>;
97
98 pub fn current_width() -> u32 {
99 unsafe { max_width() - trails.leading_zeros() }
100 }
101
102 pub fn max_width() -> u32 {
103 unsafe {
104 (mem::size_of_val(&trails)*8) as u32
105 }
106 }
107
108 pub fn indent_println(my_trails: u32, s: &str) {
109 let mut indent: String = String::new();
110 for i in 0..my_trails {
111 unsafe {
112 if trails & (1 << i) != 0 {
113 indent = indent + "| ";
114 } else {
115 indent = indent + " ";
116 }
117 }
118 }
119 println!("{}{}", indent, s);
120 }
121
122 pub fn println(s: &str) {
123 indent_println(super::PREF_INDENT, s);
124 }
125
126 fn first_avail() -> u32 {
127 unsafe {
128 for i in 0..64 {
129 if trails & (1 << i) == 0 {
130 return i;
131 }
132 }
133 }
134 panic!("exhausted trails");
135 }
136
137 pub struct D<'a> {
138 name: &'static str, i: u32, uid: u32, trail: u32, log: Log<'a>
139 }
140
141 impl<'a> fmt::Display for D<'a> {
142 fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
143 write!(w, "D({}_{}, {})", self.name, self.i, self.uid)
144 }
145 }
146
147 impl<'a> D<'a> {
148 pub fn new(name: &'static str, i: u32, log: Log<'a>) -> D<'a> {
149 unsafe {
150 let trail = first_avail();
151 let ctr = counter;
152 counter += 1;
153 trails |= (1 << trail);
154 let ret = D {
155 name: name, i: i, log: log, uid: ctr, trail: trail
156 };
157 indent_println(trail, &format!("+-- Make {}", ret));
158 ret
159 }
160 }
161 pub fn incr(&self) -> D<'a> {
162 D::new(self.name, self.i + 1, self.log)
163 }
164 }
165
166 impl<'a> Drop for D<'a> {
167 fn drop(&mut self) {
168 unsafe { trails &= !(1 << self.trail); };
169 self.log.borrow_mut().push(self.uid);
170 indent_println(self.trail, &format!("+-- Drop {}", self));
171 indent_println(::PREF_INDENT, "");
172 }
173 }
174 }