about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/test/mir-opt/end_region_cyclic.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs
new file mode 100644
index 00000000000..8f9dd79cd75
--- /dev/null
+++ b/src/test/mir-opt/end_region_cyclic.rs
@@ -0,0 +1,132 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
+// ignore-tidy-linelength
+
+// This test models a scenario with a cyclic reference. Rust obviously
+// needs to handle such cases.
+//
+// The interesting part about this test is that such case shows that
+// one cannot generally force all references to be dead before you hit
+// their EndRegion; at least, not without breaking the more important
+// property that all borrowed storage locations have their regions
+// ended strictly before their StorageDeads. (This test was inspired
+// by discussion on Issue #43481.)
+
+use std::cell::Cell;
+
+struct S<'a> {
+    r: Cell<Option<&'a S<'a>>>,
+}
+
+fn main() {
+    loop {
+        let x = S { r: Cell::new(None) };
+        x.r.set(Some(&x));
+        if query() { break; }
+        x.r.set(Some(&x));
+    }
+}
+
+fn query() -> bool { true }
+
+// END RUST SOURCE
+// START rustc.node16.SimplifyCfg-qualify-consts.after.mir
+// fn main() -> () {
+//     let mut _0: ();
+//     scope 1 {
+//         let _2: S<'35_0rs>;
+//     }
+//     let mut _1: ();
+//     let mut _3: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
+//     let mut _4: std::option::Option<&'35_0rs S<'35_0rs>>;
+//     let mut _5: ();
+//     let mut _6: &'16s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
+//     let mut _7: std::option::Option<&'35_0rs S<'35_0rs>>;
+//     let mut _8: &'35_0rs S<'35_0rs>;
+//     let mut _9: &'35_0rs S<'35_0rs>;
+//     let mut _10: ();
+//     let mut _11: bool;
+//     let mut _12: !;
+//     let mut _13: ();
+//     let mut _14: &'33s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
+//     let mut _15: std::option::Option<&'35_0rs S<'35_0rs>>;
+//     let mut _16: &'35_0rs S<'35_0rs>;
+//     let mut _17: &'35_0rs S<'35_0rs>;
+//     bb0: {
+//         goto -> bb1;
+//     }
+//     bb1: {
+//         StorageLive(_2);
+//         StorageLive(_3);
+//         StorageLive(_4);
+//         _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
+//         _3 = const <std::cell::Cell<T>>::new(_4) -> bb2;
+//     }
+//     bb2: {
+//         StorageDead(_4);
+//         _2 = S<'35_0rs> { r: _3 };
+//         StorageDead(_3);
+//         StorageLive(_6);
+//         _6 = &'16s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
+//         StorageLive(_7);
+//         StorageLive(_8);
+//         StorageLive(_9);
+//         _9 = &'35_0rs _2;
+//         _8 = &'35_0rs (*_9);
+//         _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(_8,);
+//         StorageDead(_8);
+//         _5 = const <std::cell::Cell<T>>::set(_6, _7) -> bb3;
+//     }
+//     bb3: {
+//         EndRegion('16s);
+//         StorageDead(_7);
+//         StorageDead(_6);
+//         StorageDead(_9);
+//         StorageLive(_11);
+//         _11 = const query() -> bb4;
+//     }
+//     bb4: {
+//         switchInt(_11) -> [0u8: bb6, otherwise: bb5];
+//     }
+//     bb5: {
+//         _0 = ();
+//         StorageDead(_11);
+//         EndRegion('35_0rs);
+//         StorageDead(_2);
+//         return;
+//     }
+//     bb6: {
+//         _10 = ();
+//         StorageDead(_11);
+//         StorageLive(_14);
+//         _14 = &'33s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
+//         StorageLive(_15);
+//         StorageLive(_16);
+//         StorageLive(_17);
+//         _17 = &'35_0rs _2;
+//         _16 = &'35_0rs (*_17);
+//         _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(_16,);
+//         StorageDead(_16);
+//         _13 = const <std::cell::Cell<T>>::set(_14, _15) -> bb7;
+//     }
+//     bb7: {
+//         EndRegion('33s);
+//         StorageDead(_15);
+//         StorageDead(_14);
+//         StorageDead(_17);
+//         _1 = ();
+//         EndRegion('35_0rs);
+//         StorageDead(_2);
+//         goto -> bb1;
+//     }
+// }
+// END rustc.node16.SimplifyCfg-qualify-consts.after.mir