Skip to content

Commit 5fa0b66

Browse files
committed
Test case illustrating some destruction code extent stuff.
1 parent 88080bd commit 5fa0b66

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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+
11+
// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
12+
// ignore-tidy-linelength
13+
14+
// A scenario with significant destruction code extents (which have
15+
// suffix "dce" in current `-Z identify_regions` rendering).
16+
17+
#![feature(generic_param_attrs)]
18+
#![feature(dropck_eyepatch)]
19+
20+
fn main() {
21+
// Since the second param to `D1` is may_dangle, it is legal for
22+
// the region of that parameter to end before the drop code for D1
23+
// is executed.
24+
(D1(&S1("ex1"), &S1("dang1"))).0;
25+
}
26+
27+
#[derive(Debug)]
28+
struct S1(&'static str);
29+
30+
#[derive(Debug)]
31+
struct D1<'a, 'b>(&'a S1, &'b S1);
32+
33+
// The `#[may_dangle]` means that references of type `&'b _` may be
34+
// invalid during the execution of this destructor; i.e. in this case
35+
// the destructor code is not allowed to read or write `*self.1`, while
36+
// it can read/write `*self.0`.
37+
unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> {
38+
fn drop(&mut self) {
39+
println!("D1({:?}, _)", self.0);
40+
}
41+
}
42+
43+
// Notes on the MIR output below:
44+
//
45+
// 1. The `EndRegion('10s)` is allowed to precede the `drop(_3)`
46+
// solely because of the #[may_dangle] mentioned above.
47+
//
48+
// 2. Regarding the occurrence of `EndRegion('12ds)` *after* `StorageDead(_6)`
49+
// (where we have borrows `&'12ds _6`): Eventually:
50+
//
51+
// i. this code should be rejected (by mir-borrowck), or
52+
//
53+
// ii. the MIR code generation should be changed so that the
54+
// EndRegion('12ds)` precedes `StorageDead(_6)` in the
55+
// control-flow. (Note: arielb1 views drop+storagedead as one
56+
// unit, and does not see this option as a useful avenue to
57+
// explore.), or
58+
//
59+
// iii. the presence of EndRegion should be made irrelevant by a
60+
// transformation encoding the effects of rvalue-promotion.
61+
// This may be the simplest and most-likely option; note in
62+
// particular that `StorageDead(_6)` goes away below in
63+
// rustc.node4.QualifyAndPromoteConstants.after.mir
64+
65+
// END RUST SOURCE
66+
67+
// START rustc.node4.QualifyAndPromoteConstants.before.mir
68+
// fn main() -> () {
69+
// let mut _0: ();
70+
// let mut _1: &'12ds S1;
71+
// let mut _2: &'12ds S1;
72+
// let mut _3: D1<'12ds, '10s>;
73+
// let mut _4: &'12ds S1;
74+
// let mut _5: &'12ds S1;
75+
// let mut _6: S1;
76+
// let mut _7: &'10s S1;
77+
// let mut _8: &'10s S1;
78+
// let mut _9: S1;
79+
//
80+
// bb0: {
81+
// StorageLive(_2);
82+
// StorageLive(_3);
83+
// StorageLive(_4);
84+
// StorageLive(_5);
85+
// StorageLive(_6);
86+
// _6 = S1::{{constructor}}(const "ex1",);
87+
// _5 = &'12ds _6;
88+
// _4 = &'12ds (*_5);
89+
// StorageLive(_7);
90+
// StorageLive(_8);
91+
// StorageLive(_9);
92+
// _9 = S1::{{constructor}}(const "dang1",);
93+
// _8 = &'10s _9;
94+
// _7 = &'10s (*_8);
95+
// _3 = D1<'12ds, '10s>::{{constructor}}(_4, _7);
96+
// EndRegion('10s);
97+
// StorageDead(_7);
98+
// StorageDead(_4);
99+
// _2 = (_3.0: &'12ds S1);
100+
// _1 = _2;
101+
// StorageDead(_2);
102+
// drop(_3) -> bb1;
103+
// }
104+
//
105+
// bb1: {
106+
// StorageDead(_3);
107+
// StorageDead(_8);
108+
// StorageDead(_9);
109+
// StorageDead(_5);
110+
// StorageDead(_6);
111+
// EndRegion('12ds);
112+
// _0 = ();
113+
// return;
114+
// }
115+
// }
116+
// END rustc.node4.QualifyAndPromoteConstants.before.mir
117+
118+
// START rustc.node4.QualifyAndPromoteConstants.after.mir
119+
// fn main() -> () {
120+
// let mut _0: ();
121+
// let mut _1: &'12ds S1;
122+
// let mut _2: &'12ds S1;
123+
// let mut _3: D1<'12ds, '10s>;
124+
// let mut _4: &'12ds S1;
125+
// let mut _5: &'12ds S1;
126+
// let mut _6: S1;
127+
// let mut _7: &'10s S1;
128+
// let mut _8: &'10s S1;
129+
// let mut _9: S1;
130+
//
131+
// bb0: {
132+
// StorageLive(_2);
133+
// StorageLive(_3);
134+
// StorageLive(_4);
135+
// StorageLive(_5);
136+
// _5 = promoted1;
137+
// _4 = &'12ds (*_5);
138+
// StorageLive(_7);
139+
// StorageLive(_8);
140+
// _8 = promoted0;
141+
// _7 = &'10s (*_8);
142+
// _3 = D1<'12ds, '10s>::{{constructor}}(_4, _7);
143+
// EndRegion('10s);
144+
// StorageDead(_7);
145+
// StorageDead(_4);
146+
// _2 = (_3.0: &'12ds S1);
147+
// _1 = _2;
148+
// StorageDead(_2);
149+
// drop(_3) -> bb1;
150+
// }
151+
//
152+
// bb1: {
153+
// StorageDead(_3);
154+
// StorageDead(_8);
155+
// StorageDead(_5);
156+
// EndRegion('12ds);
157+
// _0 = ();
158+
// return;
159+
// }
160+
// }
161+
// END rustc.node4.QualifyAndPromoteConstants.after.mir

0 commit comments

Comments
 (0)