Auto merge of #61872 - matthewjasper:refactor-mir-drop-gen, r=nikomatsakis

Clean up MIR drop generation

* Don't assign twice to the destination of a `while` loop containing a `break` expression
* Use `as_temp` to evaluate statement expression
* Avoid consecutive `StorageLive`s for the condition of a `while` loop
* Unify `return`, `break` and `continue` handling, and move it to `scopes.rs`
* Make some of the `scopes.rs` internals private
* Don't use `Place`s that are always `Local`s in MIR drop generation

Closes #42371
Closes #61579
Closes #61731
Closes #61834
Closes #61910
Closes #62115
This commit is contained in:
bors 2019-06-26 04:42:34 +00:00
commit d3e2cec292
27 changed files with 536 additions and 468 deletions

View file

@ -24,7 +24,7 @@ impl Drop for S {
// let mut _0: ();
// let _1: std::boxed::Box<S>;
// let mut _2: std::boxed::Box<S>;
// let mut _3: ();
// let _3: ();
// let mut _4: std::boxed::Box<S>;
// scope 1 {
// }
@ -50,6 +50,7 @@ impl Drop for S {
//
// bb4: {
// StorageDead(_2);
// StorageLive(_3);
// StorageLive(_4);
// _4 = move _1;
// _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
@ -69,6 +70,7 @@ impl Drop for S {
//
// bb8: {
// StorageDead(_4);
// StorageDead(_3);
// _0 = ();
// drop(_1) -> bb9;
// }

View file

@ -61,12 +61,14 @@ fn main() {
// END rustc.foo.CopyPropagation.after.mir
// START rustc.bar.CopyPropagation.before.mir
// bb0: {
// StorageLive(_2);
// StorageLive(_3);
// _3 = _1;
// _2 = const dummy(move _3) -> bb1;
// }
// bb1: {
// StorageDead(_3);
// StorageDead(_2);
// _1 = const 5u8;
// ...
// return;

View file

@ -18,6 +18,7 @@ fn main() {
// }
// bb1: {
// StorageDead(_3);
// StorageDead(_2);
// goto -> bb5;
// }
// bb2: {
@ -36,6 +37,7 @@ fn main() {
// goto -> bb3;
// }
// bb7: {
// StorageLive(_2);
// StorageLive(_3);
// goto -> bb1;
// }

View file

@ -54,6 +54,7 @@ fn main() {
// }
// bb2: {
// ...
// StorageLive(_6);
// StorageLive(_7);
// _7 = move _2;
// _6 = const take::<Foo>(move _7) -> [return: bb9, unwind: bb8];
@ -81,16 +82,20 @@ fn main() {
// }
// bb8 (cleanup): {
// StorageDead(_7);
// StorageDead(_6);
// goto -> bb7;
// }
// bb9: {
// StorageDead(_7);
// StorageDead(_6);
// StorageLive(_8);
// StorageLive(_9);
// _9 = move _3;
// _8 = const take::<Bar>(move _9) -> [return: bb10, unwind: bb11];
// }
// bb10: {
// StorageDead(_9);
// StorageDead(_8);
// ...
// StorageDead(_3);
// StorageDead(_2);
@ -98,6 +103,7 @@ fn main() {
// }
// bb11 (cleanup): {
// StorageDead(_9);
// StorageDead(_8);
// goto -> bb7;
// }
// bb12: {

View file

@ -25,6 +25,7 @@ fn main() {
// falseUnwind -> [real: bb3, cleanup: bb1];
// }
// bb3: {
// StorageLive(_3);
// StorageLive(_4);
// _4 = _1;
// FakeRead(ForMatchedPlace, _4);
@ -34,6 +35,7 @@ fn main() {
// bb5: {
// _3 = ();
// StorageDead(_4);
// StorageDead(_3);
// _1 = const true;
// _2 = ();
// goto -> bb2;
@ -41,6 +43,7 @@ fn main() {
// bb6: {
// _0 = ();
// StorageDead(_4);
// StorageDead(_3);
// StorageDead(_1);
// return;
// }

View file

@ -42,7 +42,7 @@ impl S {
// START rustc.test.ElaborateDrops.after.mir
// let mut _0: ();
// let _1: S;
// let mut _3: ();
// let _3: ();
// let mut _4: S;
// let mut _5: S;
// let mut _6: bool;

View file

@ -21,7 +21,7 @@ fn main() {
// let _2: i32;
// let mut _3: bool;
// let mut _4: !;
// let mut _5: ();
// let _5: ();
// let mut _6: &i32;
// scope 1 {
// }
@ -73,12 +73,14 @@ fn main() {
// bb12: {
// FakeRead(ForLet, _2);
// StorageDead(_3);
// StorageLive(_5);
// StorageLive(_6);
// _6 = &_2;
// _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb4];
// }
// bb13: {
// StorageDead(_6);
// StorageDead(_5);
// _1 = ();
// StorageDead(_2);
// goto -> bb1;

View file

@ -25,6 +25,7 @@ fn main() {
// bb3: { // Entry into the loop
// _1 = ();
// StorageDead(_2);
// StorageDead(_1);
// goto -> bb5;
// }
// ...

View file

@ -103,10 +103,6 @@ fn main() {
// bb10: { // `else` block - first time
// _9 = (*_6);
// StorageDead(_10);
// FakeRead(ForMatchGuard, _3);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// FakeRead(ForGuardBinding, _8);
// switchInt(move _9) -> [false: bb16, otherwise: bb15];
// }
// bb11: { // `return 3` - first time
@ -128,6 +124,10 @@ fn main() {
// }
// bb15: {
// StorageDead(_9);
// FakeRead(ForMatchGuard, _3);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// FakeRead(ForGuardBinding, _8);
// StorageLive(_5);
// _5 = (_2.1: bool);
// StorageLive(_7);
@ -159,10 +159,6 @@ fn main() {
// bb19: { // `else` block - second time
// _12 = (*_6);
// StorageDead(_13);
// FakeRead(ForMatchGuard, _3);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// FakeRead(ForGuardBinding, _8);
// switchInt(move _12) -> [false: bb22, otherwise: bb21];
// }
// bb20: {
@ -175,6 +171,10 @@ fn main() {
// }
// bb21: { // bindings for arm 1
// StorageDead(_12);
// FakeRead(ForMatchGuard, _3);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// FakeRead(ForGuardBinding, _8);
// StorageLive(_5);
// _5 = (_2.0: bool);
// StorageLive(_7);

View file

@ -71,12 +71,12 @@ fn main() {
// _7 = const guard() -> [return: bb7, unwind: bb1];
// }
// bb7: { // end of guard
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// switchInt(move _7) -> [false: bb9, otherwise: bb8];
// }
// bb8: { // arm1
// StorageDead(_7);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// StorageLive(_5);
// _5 = ((_2 as Some).0: i32);
// StorageLive(_8);
@ -138,12 +138,12 @@ fn main() {
// _7 = const guard() -> [return: bb6, unwind: bb1];
// }
// bb6: { // end of guard
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// switchInt(move _7) -> [false: bb8, otherwise: bb7];
// }
// bb7: {
// StorageDead(_7);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForGuardBinding, _6);
// StorageLive(_5);
// _5 = ((_2 as Some).0: i32);
// StorageLive(_8);
@ -209,12 +209,12 @@ fn main() {
// _8 = const guard() -> [return: bb6, unwind: bb1];
// }
// bb6: { //end of guard1
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForGuardBinding, _7);
// switchInt(move _8) -> [false: bb8, otherwise: bb7];
// }
// bb7: {
// StorageDead(_8);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForGuardBinding, _7);
// StorageLive(_6);
// _6 = ((_2 as Some).0: i32);
// _1 = const 1i32;
@ -245,12 +245,12 @@ fn main() {
// }
// bb11: { // end of guard2
// StorageDead(_13);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForGuardBinding, _11);
// switchInt(move _12) -> [false: bb13, otherwise: bb12];
// }
// bb12: { // binding4 & arm4
// StorageDead(_12);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForGuardBinding, _11);
// StorageLive(_10);
// _10 = ((_2 as Some).0: i32);
// _1 = const 3i32;

View file

@ -54,11 +54,11 @@ fn main() {
// _8 = &shallow _1;
// StorageLive(_9);
// _9 = _2;
// FakeRead(ForMatchGuard, _8);
// switchInt(move _9) -> [false: bb11, otherwise: bb10];
// }
// bb10: {
// StorageDead(_9);
// FakeRead(ForMatchGuard, _8);
// _3 = const 0i32;
// goto -> bb14;
// }
@ -75,6 +75,7 @@ fn main() {
// goto -> bb14;
// }
// bb14: {
// StorageDead(_3);
// _0 = ();
// StorageDead(_2);
// StorageDead(_1);

View file

@ -22,9 +22,9 @@ fn main() {
// END RUST SOURCE
// START rustc.main.nll.0.mir
// | '_#2r | U0 | {bb2[0..=8], bb3[0], bb5[0..=1]}
// | '_#3r | U0 | {bb2[1..=8], bb3[0], bb5[0..=1]}
// | '_#4r | U0 | {bb2[4..=8], bb3[0], bb5[0..=1]}
// | '_#2r | U0 | {bb2[0..=8], bb3[0], bb5[0..=2]}
// | '_#3r | U0 | {bb2[1..=8], bb3[0], bb5[0..=2]}
// | '_#4r | U0 | {bb2[4..=8], bb3[0], bb5[0..=2]}
// END rustc.main.nll.0.mir
// START rustc.main.nll.0.mir
// let _2: &'_#3r usize;

View file

@ -38,14 +38,14 @@ fn main() {
// _7 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
// StorageLive(_8);
// _8 = _2;
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForMatchGuard, _6);
// FakeRead(ForMatchGuard, _7);
// switchInt(move _8) -> [false: bb6, otherwise: bb5];
// }
// bb5: {
// StorageDead(_8);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForMatchGuard, _6);
// FakeRead(ForMatchGuard, _7);
// _0 = const 0i32;
// goto -> bb7;
// }
@ -84,14 +84,14 @@ fn main() {
// nop;
// StorageLive(_8);
// _8 = _2;
// nop;
// nop;
// nop;
// nop;
// switchInt(move _8) -> [false: bb6, otherwise: bb5];
// }
// bb5: {
// StorageDead(_8);
// nop;
// nop;
// nop;
// nop;
// _0 = const 0i32;
// goto -> bb7;
// }

View file

@ -12,6 +12,7 @@ fn main() {
// StorageLive(_1);
// _1 = const 0i32;
// FakeRead(ForLet, _1);
// StorageLive(_2);
// StorageLive(_3);
// StorageLive(_4);
// StorageLive(_5);
@ -23,6 +24,7 @@ fn main() {
// _2 = ();
// StorageDead(_4);
// StorageDead(_3);
// StorageDead(_2);
// StorageLive(_6);
// _6 = const 1i32;
// FakeRead(ForLet, _6);

View file

@ -0,0 +1,59 @@
// Test that we correctly generate StorageDead statements for while loop
// conditions on all branches
fn get_bool(c: bool) -> bool {
c
}
fn while_loop(c: bool) {
while get_bool(c) {
if get_bool(c) {
break;
}
}
}
fn main() {
while_loop(false);
}
// END RUST SOURCE
// START rustc.while_loop.PreCodegen.after.mir
// bb0: {
// StorageLive(_2);
// StorageLive(_3);
// _3 = _1;
// _2 = const get_bool(move _3) -> bb2;
// }
// bb1: {
// return;
// }
// bb2: {
// StorageDead(_3);
// switchInt(move _2) -> [false: bb4, otherwise: bb3];
// }
// bb3: {
// StorageDead(_2);
// StorageLive(_4);
// StorageLive(_5);
// _5 = _1;
// _4 = const get_bool(move _5) -> bb5;
// }
// bb4: {
// StorageDead(_2);
// goto -> bb1;
// }
// bb5: {
// StorageDead(_5);
// switchInt(_4) -> [false: bb6, otherwise: bb7];
// }
// bb6: {
// StorageDead(_4);
// goto -> bb0;
// }
// bb7: {
// StorageDead(_4);
// goto -> bb1;
// }
// END rustc.while_loop.PreCodegen.after.mir

View file

@ -0,0 +1,32 @@
// Test that we don't consider temporaries for statement expressions as live
// across yields
// check-pass
// edition:2018
#![feature(async_await, generators, generator_trait)]
use std::ops::Generator;
async fn drop_and_await() {
async {};
async {}.await;
}
fn drop_and_yield() {
let x = || {
String::new();
yield;
};
Box::pin(x).as_mut().resume();
let y = static || {
String::new();
yield;
};
Box::pin(y).as_mut().resume();
}
fn main() {
drop_and_await();
drop_and_yield();
}

View file

@ -0,0 +1,11 @@
// We used to incorrectly assign to `x` twice when generating MIR for this
// function, preventing this from compiling.
// check-pass
fn main() {
let x = while false {
break;
};
let y = 'l: while break 'l {};
}