提交 9dd55276 编写于 作者: F Felix S. Klock II

Leverage mir-opt to encode tests for `EndRegion`.

The tests use `-Z identify_regions` so one can eyeball output for
sanity. The tests with closures use `-Z span_free_formats` so that
host-specific paths do not get embedded into the dumped MIR.

The tests check against MIR dump output immediately prior to borrowck
(determined by hand to be the dump from after the "qualify-consts"
pass) since that is when `EndRegion` will be most relevant in the near
term.
上级 0a5211e8
......@@ -22,7 +22,32 @@ All the test information is in comments so the test is runnable.
For each $file_name, compiletest expects [$expected_line_0, ...,
$expected_line_N] to appear in the dumped MIR in order. Currently it allows
other non-matched lines before, after and in-between.
other non-matched lines before, after and in-between. Note that this includes
lines that end basic blocks or begin new ones; it is good practice
in your tests to include the terminator for each of your basic blocks as an
internal sanity check guarding against a test like:
```
bb0: {
StorageLive(_1);
_1 = const true;
StorageDead(_1);
}
```
that will inadvertantly pattern-matching against:
```
bb0: {
StorageLive(_1);
_1 = const true;
goto -> bb1
}
bb1: {
StorageDead(_1);
return;
}
```
Lines match ignoring whitespace, and the prefix "//" is removed.
......
// 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
// ignore-tidy-linelength
// This is just about the simplest program that exhibits an EndRegion.
fn main() {
let a = 3;
let b = &a;
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// let mut _0: ();
// let _1: i32;
// let _2: &'6_1rce i32;
//
// bb0: {
// StorageLive(_1);
// _1 = const 3i32;
// StorageLive(_2);
// _2 = &'6_1rce _1;
// _0 = ();
// StorageDead(_2);
// EndRegion('6_1rce);
// StorageDead(_1);
// return;
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// We will EndRegion for borrows in a loop that occur before break but
// not those after break.
fn main() {
loop {
let a = true;
let b = &a;
if a { break; }
let c = &a;
}
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// let mut _0: ();
// let _2: bool;
// let _3: &'7_1rce bool;
// let _7: &'7_3rce bool;
// let mut _4: ();
// let mut _5: bool;
// bb0: {
// goto -> bb1;
// }
// bb1: {
// StorageLive(_2);
// _2 = const true;
// StorageLive(_3);
// _3 = &'7_1rce _2;
// StorageLive(_5);
// _5 = _2;
// switchInt(_5) -> [0u8: bb3, otherwise: bb2];
// }
// bb2: {
// _0 = ();
// StorageDead(_5);
// StorageDead(_3);
// EndRegion('7_1rce);
// StorageDead(_2);
// return;
// }
// bb3: {
// StorageDead(_5);
// StorageLive(_7);
// _7 = &'7_3rce _2;
// _1 = ();
// StorageDead(_7);
// EndRegion('7_3rce);
// StorageDead(_3);
// EndRegion('7_1rce);
// StorageDead(_2);
// goto -> bb1;
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// Binding the borrow's subject outside the loop does not increase the
// scope of the borrow.
fn main() {
let mut a;
loop {
a = true;
let b = &a;
if a { break; }
let c = &a;
}
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// let mut _0: ();
// let mut _1: bool;
// let _3: &'9_1rce bool;
// let _7: &'9_3rce bool;
// let mut _2: ();
// let mut _4: ();
// let mut _5: bool;
//
// bb0: {
// StorageLive(_1);
// goto -> bb1;
// }
// bb1: {
// _1 = const true;
// StorageLive(_3);
// _3 = &'9_1rce _1;
// StorageLive(_5);
// _5 = _1;
// switchInt(_5) -> [0u8: bb3, otherwise: bb2];
// }
// bb2: {
// _0 = ();
// StorageDead(_5);
// StorageDead(_3);
// EndRegion('9_1rce);
// StorageDead(_1);
// return;
// }
// bb3: {
// _4 = ();
// StorageDead(_5);
// StorageLive(_7);
// _7 = &'9_3rce _1;
// _2 = ();
// StorageDead(_7);
// EndRegion('9_3rce);
// StorageDead(_3);
// EndRegion('9_1rce);
// goto -> bb1;
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// Unwinding should EndRegion for in-scope borrows: Direct borrows.
fn main() {
let d = D(0);
let a = 0;
let b = &a;
foo(*b);
let c = &a;
}
struct D(i32);
impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
fn foo(i: i32) {
if i > 0 { panic!("im positive"); }
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// let mut _0: ();
// let _1: D;
// let _3: i32;
// let _4: &'6_2rce i32;
// let _7: &'6_4rce i32;
// let mut _5: ();
// let mut _6: i32;
//
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// StorageLive(_3);
// _3 = const 0i32;
// StorageLive(_4);
// _4 = &'6_2rce _3;
// StorageLive(_6);
// _6 = (*_4);
// _5 = const foo(_6) -> [return: bb2, unwind: bb3];
// }
// bb1: {
// resume;
// }
// bb2: {
// StorageDead(_6);
// StorageLive(_7);
// _7 = &'6_4rce _3;
// _0 = ();
// StorageDead(_7);
// EndRegion('6_4rce);
// StorageDead(_4);
// EndRegion('6_2rce);
// StorageDead(_3);
// drop(_1) -> bb4;
// }
// bb3: {
// EndRegion('6_2rce);
// drop(_1) -> bb1;
// }
// bb4: {
// StorageDead(_1);
// return;
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// Unwinding should EndRegion for in-scope borrows: Borrowing via by-ref closure.
fn main() {
let d = D(0);
foo(|| -> i32 { d.0 });
}
struct D(i32);
impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
fn foo<F>(f: F) where F: FnOnce() -> i32 {
if f() > 0 { panic!("im positive"); }
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// fn main() -> () {
// let mut _0: ();
// let _1: D;
// let mut _2: ();
// let mut _3: ();
// let mut _4: [closure@NodeId(18) d: &'19mce D];
// let mut _5: &'19mce D;
//
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// StorageLive(_4);
// StorageLive(_5);
// _5 = &'19mce _1;
// _4 = [closure@NodeId(18)] { d: _5 };
// StorageDead(_5);
// _3 = const foo(_4) -> [return: bb2, unwind: bb3];
// }
// bb1: {
// resume;
// }
// bb2: {
// StorageDead(_4);
// EndRegion('19mce);
// _0 = ();
// drop(_1) -> bb4;
// }
// bb3: {
// EndRegion('19mce);
// drop(_1) -> bb1;
// }
// bb4: {
// StorageDead(_1);
// return;
// }
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// START rustc.node18.SimplifyCfg-qualify-consts.after.mir
// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'19mce D]) -> i32 {
// let mut _0: i32;
// let mut _2: i32;
//
// bb0: {
// StorageLive(_2);
// _2 = ((*(_1.0: &'19mce D)).0: i32);
// _0 = _2;
// StorageDead(_2);
// return;
// }
// END rustc.node18.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// Unwinding should EndRegion for in-scope borrows: 2nd borrow within by-ref closure.
fn main() {
let d = D(0);
foo(|| -> i32 { let r = &d; r.0 });
}
struct D(i32);
impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
fn foo<F>(f: F) where F: FnOnce() -> i32 {
if f() > 0 { panic!("im positive"); }
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// let mut _0: ();
// let _1: D;
// let mut _2: ();
// let mut _3: ();
// let mut _4: [closure@NodeId(22) d:&'23mce D];
// let mut _5: &'23mce D;
//
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// StorageLive(_4);
// StorageLive(_5);
// _5 = &'23mce _1;
// _4 = [closure@NodeId(22)] { d: _5 };
// StorageDead(_5);
// _3 = const foo(_4) -> [return: bb2, unwind: bb3];
// }
// bb1: {
// resume;
// }
// bb2: {
// StorageDead(_4);
// EndRegion('23mce);
// _0 = ();
// drop(_1) -> bb4;
// }
// bb3: {
// EndRegion('23mce);
// drop(_1) -> bb1;
// }
// bb4: {
// StorageDead(_1);
// return;
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// START rustc.node22.SimplifyCfg-qualify-consts.after.mir
// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'23mce D]) -> i32 {
// let mut _0: i32;
// let _2: &'14_0rce D;
// let mut _3: i32;
//
// bb0: {
// StorageLive(_2);
// _2 = &'14_0rce (*(_1.0: &'23mce D));
// StorageLive(_3);
// _3 = ((*_2).0: i32);
// _0 = _3;
// StorageDead(_3);
// StorageDead(_2);
// EndRegion('14_0rce);
// return;
// }
// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// Unwinding should EndRegion for in-scope borrows: Borrow of moved data.
fn main() {
let d = D(0);
foo(move || -> i32 { let r = &d; r.0 });
}
struct D(i32);
impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
fn foo<F>(f: F) where F: FnOnce() -> i32 {
if f() > 0 { panic!("im positive"); }
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// fn main() -> () {
// let mut _0: ();
// let _1: D;
// let mut _2: ();
// let mut _3: ();
// let mut _4: [closure@NodeId(22) d:D];
// let mut _5: D;
//
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// StorageLive(_4);
// StorageLive(_5);
// _5 = _1;
// _4 = [closure@NodeId(22)] { d: _5 };
// drop(_5) -> [return: bb4, unwind: bb3];
// }
// bb1: {
// resume;
// }
// bb2: {
// drop(_1) -> bb1;
// }
// bb3: {
// drop(_4) -> bb2;
// }
// bb4: {
// StorageDead(_5);
// _3 = const foo(_4) -> [return: bb5, unwind: bb3];
// }
// bb5: {
// drop(_4) -> [return: bb6, unwind: bb2];
// }
// bb6: {
// StorageDead(_4);
// _0 = ();
// drop(_1) -> bb7;
// }
// bb7: {
// StorageDead(_1);
// return;
// }
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// START rustc.node22.SimplifyCfg-qualify-consts.after.mir
// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 {
// let mut _0: i32;
// let _2: &'14_0rce D;
// let mut _3: ();
// let mut _4: i32;
//
// bb0: {
// StorageLive(_2);
// _2 = &'14_0rce (_1.0: D);
// StorageLive(_4);
// _4 = ((*_2).0: i32);
// _0 = _4;
// StorageDead(_4);
// StorageDead(_2);
// EndRegion('14_0rce);
// drop(_1) -> bb1;
// }
// bb1: {
// return;
// }
// }
// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// Unwinding should EndRegion for in-scope borrows: Move of borrow into closure.
fn main() {
let d = D(0);
let r = &d;
foo(move || -> i32 { r.0 });
}
struct D(i32);
impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
fn foo<F>(f: F) where F: FnOnce() -> i32 {
if f() > 0 { panic!("im positive"); }
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// fn main() -> () {
// let mut _0: ();
// let _1: D;
// let _3: &'6_1rce D;
// let mut _2: ();
// let mut _4: ();
// let mut _5: [closure@NodeId(22) r:&'6_1rce D];
// let mut _6: &'6_1rce D;
//
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// StorageLive(_3);
// _3 = &'6_1rce _1;
// StorageLive(_5);
// StorageLive(_6);
// _6 = _3;
// _5 = [closure@NodeId(22)] { r: _6 };
// StorageDead(_6);
// _4 = const foo(_5) -> [return: bb2, unwind: bb3];
// }
// bb1: {
// resume;
// }
// bb2: {
// StorageDead(_5);
// _0 = ();
// StorageDead(_3);
// EndRegion('6_1rce);
// drop(_1) -> bb4;
// }
// bb3: {
// EndRegion('6_1rce);
// drop(_1) -> bb1;
// }
// bb4: {
// StorageDead(_1);
// return;
// }
// }
// END rustc.node4.SimplifyCfg-qualify-consts.after.mir
// START rustc.node22.SimplifyCfg-qualify-consts.after.mir
// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'6_1rce D]) -> i32 {
// let mut _0: i32;
// let mut _2: i32;
//
// bb0: {
// StorageLive(_2);
// _2 = ((*(_1.0: &'6_1rce D)).0: i32);
// _0 = _2;
// StorageDead(_2);
// return;
// }
// }
// END rustc.node22.SimplifyCfg-qualify-consts.after.mir
// 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
// ignore-tidy-linelength
// This test models a scenario that arielb1 found during review.
// Namely, any filtering of EndRegions must ensure to continue to emit
// any necessary EndRegions that occur earlier in the source than the
// first borrow involving that region.
//
// It is tricky to actually construct examples of this, which is the
// main reason that I am keeping this test even though I have now
// removed the pre-filter that motivated the test in the first place.
fn main() {
let mut second_iter = false;
let x = 3;
'a: loop {
let mut y;
loop {
if second_iter {
break 'a; // want to generate `EndRegion('a)` here
} else {
y = &/*'a*/ x;
}
second_iter = true;
}
}
}
// END RUST SOURCE
// START rustc.node4.SimplifyCfg-qualify-consts.after.mir
// fn main() -> () {
// let mut _0: ();
// let mut _1: bool;
// let _2: i32;
// let mut _4: &'13_0rce i32;
// let mut _3: ();
// let mut _5: !;
// let mut _6: ();
// let mut _7: bool;
// let mut _8: !;
//
// bb0: {
// StorageLive(_1);
// _1 = const false;
// StorageLive(_2);
// _2 = const 3i32;
// StorageLive(_4);
// goto -> bb1;
// }
//
// bb1: {
// StorageLive(_7);
// _7 = _1;
// switchInt(_7) -> [0u8: bb3, otherwise: bb2];
// }
//
// bb2: {
// _0 = ();
// StorageDead(_7);
// StorageDead(_4);
// EndRegion('13_0rce);
// StorageDead(_2);
// StorageDead(_1);
// return;
// }
//
// bb3: {
// _4 = &'13_0rce _2;
// _6 = ();
// StorageDead(_7);
// _1 = const true;
// _3 = ();
// goto -> bb1;
// }
// }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册