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:
commit
d3e2cec292
27 changed files with 536 additions and 468 deletions
|
|
@ -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;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ fn main() {
|
|||
// bb3: { // Entry into the loop
|
||||
// _1 = ();
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// goto -> bb5;
|
||||
// }
|
||||
// ...
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
59
src/test/mir-opt/while-storage.rs
Normal file
59
src/test/mir-opt/while-storage.rs
Normal 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
|
||||
32
src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs
Normal file
32
src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs
Normal 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();
|
||||
}
|
||||
11
src/test/ui/nll/assign-while-to-immutable.rs
Normal file
11
src/test/ui/nll/assign-while-to-immutable.rs
Normal 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 {};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue