Skip to content

Commit 88080bd

Browse files
committed
Unit test for proper EndRegion emission on a cyclic reference.
1 parent ab46142 commit 88080bd

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

src/test/mir-opt/end_region_cyclic.rs

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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+
// This test models a scenario with a cyclic reference. Rust obviously
15+
// needs to handle such cases.
16+
//
17+
// The interesting part about this test is that such case shows that
18+
// one cannot generally force all references to be dead before you hit
19+
// their EndRegion; at least, not without breaking the more important
20+
// property that all borrowed storage locations have their regions
21+
// ended strictly before their StorageDeads. (This test was inspired
22+
// by discussion on Issue #43481.)
23+
24+
use std::cell::Cell;
25+
26+
struct S<'a> {
27+
r: Cell<Option<&'a S<'a>>>,
28+
}
29+
30+
fn main() {
31+
loop {
32+
let x = S { r: Cell::new(None) };
33+
x.r.set(Some(&x));
34+
if query() { break; }
35+
x.r.set(Some(&x));
36+
}
37+
}
38+
39+
fn query() -> bool { true }
40+
41+
// END RUST SOURCE
42+
// START rustc.node16.SimplifyCfg-qualify-consts.after.mir
43+
// fn main() -> () {
44+
// let mut _0: ();
45+
// scope 1 {
46+
// let _2: S<'35_0rs>;
47+
// }
48+
// let mut _1: ();
49+
// let mut _3: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
50+
// let mut _4: std::option::Option<&'35_0rs S<'35_0rs>>;
51+
// let mut _5: ();
52+
// let mut _6: &'16s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
53+
// let mut _7: std::option::Option<&'35_0rs S<'35_0rs>>;
54+
// let mut _8: &'35_0rs S<'35_0rs>;
55+
// let mut _9: &'35_0rs S<'35_0rs>;
56+
// let mut _10: ();
57+
// let mut _11: bool;
58+
// let mut _12: !;
59+
// let mut _13: ();
60+
// let mut _14: &'33s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
61+
// let mut _15: std::option::Option<&'35_0rs S<'35_0rs>>;
62+
// let mut _16: &'35_0rs S<'35_0rs>;
63+
// let mut _17: &'35_0rs S<'35_0rs>;
64+
// bb0: {
65+
// goto -> bb1;
66+
// }
67+
// bb1: {
68+
// StorageLive(_2);
69+
// StorageLive(_3);
70+
// StorageLive(_4);
71+
// _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
72+
// _3 = const <std::cell::Cell<T>>::new(_4) -> bb2;
73+
// }
74+
// bb2: {
75+
// StorageDead(_4);
76+
// _2 = S<'35_0rs> { r: _3 };
77+
// StorageDead(_3);
78+
// StorageLive(_6);
79+
// _6 = &'16s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
80+
// StorageLive(_7);
81+
// StorageLive(_8);
82+
// StorageLive(_9);
83+
// _9 = &'35_0rs _2;
84+
// _8 = &'35_0rs (*_9);
85+
// _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(_8,);
86+
// StorageDead(_8);
87+
// _5 = const <std::cell::Cell<T>>::set(_6, _7) -> bb3;
88+
// }
89+
// bb3: {
90+
// EndRegion('16s);
91+
// StorageDead(_7);
92+
// StorageDead(_6);
93+
// StorageDead(_9);
94+
// StorageLive(_11);
95+
// _11 = const query() -> bb4;
96+
// }
97+
// bb4: {
98+
// switchInt(_11) -> [0u8: bb6, otherwise: bb5];
99+
// }
100+
// bb5: {
101+
// _0 = ();
102+
// StorageDead(_11);
103+
// EndRegion('35_0rs);
104+
// StorageDead(_2);
105+
// return;
106+
// }
107+
// bb6: {
108+
// _10 = ();
109+
// StorageDead(_11);
110+
// StorageLive(_14);
111+
// _14 = &'33s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
112+
// StorageLive(_15);
113+
// StorageLive(_16);
114+
// StorageLive(_17);
115+
// _17 = &'35_0rs _2;
116+
// _16 = &'35_0rs (*_17);
117+
// _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(_16,);
118+
// StorageDead(_16);
119+
// _13 = const <std::cell::Cell<T>>::set(_14, _15) -> bb7;
120+
// }
121+
// bb7: {
122+
// EndRegion('33s);
123+
// StorageDead(_15);
124+
// StorageDead(_14);
125+
// StorageDead(_17);
126+
// _1 = ();
127+
// EndRegion('35_0rs);
128+
// StorageDead(_2);
129+
// goto -> bb1;
130+
// }
131+
// }
132+
// END rustc.node16.SimplifyCfg-qualify-consts.after.mir

0 commit comments

Comments
 (0)