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 000000000000..8f9dd79cd754 --- /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 or the MIT license +// , 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>>, +} + +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>>; +// let mut _4: std::option::Option<&'35_0rs S<'35_0rs>>; +// let mut _5: (); +// let mut _6: &'16s std::cell::Cell>>; +// 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>>; +// 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 >::new(_4) -> bb2; +// } +// bb2: { +// StorageDead(_4); +// _2 = S<'35_0rs> { r: _3 }; +// StorageDead(_3); +// StorageLive(_6); +// _6 = &'16s (_2.0: std::cell::Cell>>); +// 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 >::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>>); +// 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 >::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