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