Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix end region emission order #44129

Merged
merged 4 commits into from
Sep 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/librustc_mir/build/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
let scope = self.scopes.pop().unwrap();
assert_eq!(scope.region_scope, region_scope.0);

self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope);
unpack!(block = build_scope_drops(&mut self.cfg,
&scope,
&self.scopes,
block,
self.arg_count,
false));

self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope);
block.unit()
}

Expand Down Expand Up @@ -406,15 +407,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
scope.cached_exits.insert((target, region_scope.0), b);
b
};

// End all regions for scopes out of which we are breaking.
self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope);

unpack!(block = build_scope_drops(&mut self.cfg,
scope,
rest,
block,
self.arg_count,
false));

// End all regions for scopes out of which we are breaking.
self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope);
}
}
let scope = &self.scopes[len - scope_count];
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/end_region_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ fn main() {
// StorageLive(_2);
// _2 = &'10_1rs _1;
// _0 = ();
// StorageDead(_2);
// EndRegion('10_1rs);
// StorageDead(_2);
// StorageDead(_1);
// return;
// }
Expand Down
6 changes: 3 additions & 3 deletions src/test/mir-opt/end_region_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ fn main() {
// bb2: {
// _0 = ();
// StorageDead(_5);
// StorageDead(_3);
// EndRegion('23_1rs);
// StorageDead(_3);
// StorageDead(_2);
// return;
// }
Expand All @@ -56,10 +56,10 @@ fn main() {
// StorageLive(_7);
// _7 = &'23_3rs _2;
// _1 = ();
// StorageDead(_7);
// EndRegion('23_3rs);
// StorageDead(_3);
// StorageDead(_7);
// EndRegion('23_1rs);
// StorageDead(_3);
// StorageDead(_2);
// goto -> bb1;
// }
Expand Down
6 changes: 3 additions & 3 deletions src/test/mir-opt/end_region_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ fn main() {
// bb2: {
// _0 = ();
// StorageDead(_5);
// StorageDead(_3);
// EndRegion('26_1rs);
// StorageDead(_3);
// StorageDead(_1);
// return;
// }
Expand All @@ -60,10 +60,10 @@ fn main() {
// StorageLive(_7);
// _7 = &'26_3rs _1;
// _2 = ();
// StorageDead(_7);
// EndRegion('26_3rs);
// StorageDead(_3);
// StorageDead(_7);
// EndRegion('26_1rs);
// StorageDead(_3);
// goto -> bb1;
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
4 changes: 2 additions & 2 deletions src/test/mir-opt/end_region_4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ fn foo(i: i32) {
// StorageLive(_6);
// _6 = &'26_4rs _2;
// _0 = ();
// StorageDead(_6);
// EndRegion('26_4rs);
// StorageDead(_3);
// StorageDead(_6);
// EndRegion('26_2rs);
// StorageDead(_3);
// StorageDead(_2);
// drop(_1) -> bb4;
// }
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/end_region_5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// _2 = const foo(_3) -> [return: bb1, unwind: bb3];
// }
// bb1: {
// StorageDead(_3);
// EndRegion('14s);
// StorageDead(_3);
// _0 = ();
// drop(_1) -> bb4;
// }
Expand Down
4 changes: 2 additions & 2 deletions src/test/mir-opt/end_region_6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// _2 = const foo(_3) -> [return: bb1, unwind: bb3];
// }
// bb1: {
// StorageDead(_3);
// EndRegion('19s);
// StorageDead(_3);
// _0 = ();
// drop(_1) -> bb4;
// }
Expand Down Expand Up @@ -75,8 +75,8 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// _3 = ((*_2).0: i32);
// _0 = _3;
// StorageDead(_3);
// StorageDead(_2);
// EndRegion('15_0rs);
// StorageDead(_2);
// return;
// }
// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
2 changes: 1 addition & 1 deletion src/test/mir-opt/end_region_7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// _3 = ((*_2).0: i32);
// _0 = _3;
// StorageDead(_3);
// StorageDead(_2);
// EndRegion('15_0rs);
// StorageDead(_2);
// drop(_1) -> bb1;
// }
// bb1: {
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/end_region_8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// bb1: {
// StorageDead(_4);
// _0 = ();
// StorageDead(_2);
// EndRegion('21_1rs);
// StorageDead(_2);
// drop(_1) -> bb4;
// }
// bb2: {
Expand Down
7 changes: 4 additions & 3 deletions src/test/mir-opt/end_region_9.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn main() {
// let mut _0: ();
// let mut _1: bool;
// let _2: i32;
// let mut _4: &'13_0rs i32;
// let mut _4: &'33_0rs i32;
// let mut _3: ();
// let mut _5: !;
// let mut _6: ();
Expand All @@ -67,19 +67,20 @@ fn main() {
// bb2: {
// _0 = ();
// StorageDead(_7);
// EndRegion('33_0rs);
// StorageDead(_4);
// EndRegion('13_0rs);
// StorageDead(_2);
// StorageDead(_1);
// return;
// }
//
// bb3: {
// _4 = &'13_0rs _2;
// _4 = &'33_0rs _2;
// _6 = ();
// StorageDead(_7);
// _1 = const true;
// _3 = ();
// goto -> bb1;
// }
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
132 changes: 132 additions & 0 deletions src/test/mir-opt/end_region_cyclic.rs
Original file line number Diff line number Diff line change
@@ -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
Loading