Use `as_temp` to evaluate statement expressions
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index 749cd6f..7ea08b1 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -78,7 +78,7 @@
let source_info = this.source_info(span);
for stmt in stmts {
- let Stmt { kind, opt_destruction_scope, span: stmt_span } = this.hir.mirror(stmt);
+ let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
match kind {
StmtKind::Expr { scope, expr } => {
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
@@ -87,7 +87,7 @@
let si = (scope, source_info);
this.in_scope(si, LintLevel::Inherited, |this| {
let expr = this.hir.mirror(expr);
- this.stmt_expr(block, expr, Some(stmt_span))
+ this.stmt_expr(block, expr, Some(scope))
})
}));
}
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index 4463e7f..3c5eafb 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -1,6 +1,7 @@
use crate::build::scope::BreakableScope;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use crate::hair::*;
+use rustc::middle::region;
use rustc::mir::*;
impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -8,14 +9,13 @@
/// If the original expression was an AST statement,
/// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
/// span of that statement (including its semicolon, if any).
- /// Diagnostics use this span (which may be larger than that of
- /// `expr`) to identify when statement temporaries are dropped.
- pub fn stmt_expr(&mut self,
- mut block: BasicBlock,
- expr: Expr<'tcx>,
- opt_stmt_span: Option<StatementSpan>)
- -> BlockAnd<()>
- {
+ /// The scope is used if a statement temporary must be dropped.
+ pub fn stmt_expr(
+ &mut self,
+ mut block: BasicBlock,
+ expr: Expr<'tcx>,
+ statement_scope: Option<region::Scope>,
+ ) -> BlockAnd<()> {
let this = self;
let expr_span = expr.span;
let source_info = this.source_info(expr.span);
@@ -30,7 +30,7 @@
} => {
let value = this.hir.mirror(value);
this.in_scope((region_scope, source_info), lint_level, |this| {
- this.stmt_expr(block, value, opt_stmt_span)
+ this.stmt_expr(block, value, statement_scope)
})
}
ExprKind::Assign { lhs, rhs } => {
@@ -199,7 +199,11 @@
block.unit()
}
_ => {
- let expr_ty = expr.ty;
+ assert!(
+ statement_scope.is_some(),
+ "Should not be calling `stmt_expr` on a general expression \
+ without a statement scope",
+ );
// Issue #54382: When creating temp for the value of
// expression like:
@@ -208,48 +212,34 @@
//
// it is usually better to focus on `the_value` rather
// than the entirety of block(s) surrounding it.
- let mut temp_span = expr_span;
- let mut temp_in_tail_of_block = false;
- if let ExprKind::Block { body } = expr.kind {
- if let Some(tail_expr) = &body.expr {
- let mut expr = tail_expr;
- while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
- if let Some(subtail_expr) = &subblock.expr {
- expr = subtail_expr
- } else {
- break;
+ let adjusted_span = (|| {
+ if let ExprKind::Block { body } = expr.kind {
+ if let Some(tail_expr) = &body.expr {
+ let mut expr = tail_expr;
+ while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
+ if let Some(subtail_expr) = &subblock.expr {
+ expr = subtail_expr
+ } else {
+ break;
+ }
}
- }
- temp_span = expr.span;
- temp_in_tail_of_block = true;
- }
- }
-
- let temp = {
- let mut local_decl = LocalDecl::new_temp(expr.ty.clone(), temp_span);
- if temp_in_tail_of_block {
- if this.block_context.currently_ignores_tail_results() {
- local_decl = local_decl.block_tail(BlockTailInfo {
+ this.block_context.push(BlockFrame::TailExpr {
tail_result_is_ignored: true
});
+ return Some(expr.span);
}
}
- let temp = this.local_decls.push(local_decl);
- let place = Place::from(temp);
- debug!("created temp {:?} for expr {:?} in block_context: {:?}",
- temp, expr, this.block_context);
- place
- };
- unpack!(block = this.into(&temp, block, expr));
+ None
+ })();
- // Attribute drops of the statement's temps to the
- // semicolon at the statement's end.
- let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span {
- None => expr_span,
- Some(StatementSpan(span)) => span,
- });
+ let temp = unpack!(block =
+ this.as_temp(block, statement_scope, expr, Mutability::Not));
- unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
+ if let Some(span) = adjusted_span {
+ this.local_decls[temp].source_info.span = span;
+ this.block_context.pop();
+ }
+
block.unit()
}
}
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index db58a70..c5b5f25 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -806,27 +806,6 @@
}
/// Utility function for *non*-scope code to build their own drops
- pub fn build_drop(&mut self,
- block: BasicBlock,
- span: Span,
- location: Place<'tcx>,
- ty: Ty<'tcx>) -> BlockAnd<()> {
- if !self.hir.needs_drop(ty) {
- return block.unit();
- }
- let source_info = self.source_info(span);
- let next_target = self.cfg.start_new_block();
- let diverge_target = self.diverge_cleanup();
- self.cfg.terminate(block, source_info,
- TerminatorKind::Drop {
- location,
- target: next_target,
- unwind: Some(diverge_target),
- });
- next_target.unit()
- }
-
- /// Utility function for *non*-scope code to build their own drops
pub fn build_drop_and_replace(&mut self,
block: BasicBlock,
span: Span,
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index d593205..9a73842 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -49,7 +49,6 @@
for (index, stmt) in stmts.iter().enumerate() {
let hir_id = stmt.hir_id;
let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
- let stmt_span = StatementSpan(cx.tcx.hir().span(hir_id));
match stmt.node {
hir::StmtKind::Expr(ref expr) |
hir::StmtKind::Semi(ref expr) => {
@@ -62,7 +61,6 @@
expr: expr.to_ref(),
},
opt_destruction_scope: opt_dxn_ext,
- span: stmt_span,
})))
}
hir::StmtKind::Item(..) => {
@@ -107,7 +105,6 @@
lint_level: LintLevel::Explicit(local.hir_id),
},
opt_destruction_scope: opt_dxn_ext,
- span: stmt_span,
})));
}
}
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 4694241..5431a31 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -56,13 +56,9 @@
}
#[derive(Clone, Debug)]
-pub struct StatementSpan(pub Span);
-
-#[derive(Clone, Debug)]
pub struct Stmt<'tcx> {
pub kind: StmtKind<'tcx>,
pub opt_destruction_scope: Option<region::Scope>,
- pub span: StatementSpan,
}
#[derive(Clone, Debug)]
diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index 9f55d84..d9fa3d3 100644
--- a/src/test/mir-opt/box_expr.rs
+++ b/src/test/mir-opt/box_expr.rs
@@ -24,7 +24,7 @@
// 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 @@
//
// 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 @@
//
// bb8: {
// StorageDead(_4);
+// StorageDead(_3);
// _0 = ();
// drop(_1) -> bb9;
// }
diff --git a/src/test/mir-opt/copy_propagation_arg.rs b/src/test/mir-opt/copy_propagation_arg.rs
index 4e05484..5e5fed1 100644
--- a/src/test/mir-opt/copy_propagation_arg.rs
+++ b/src/test/mir-opt/copy_propagation_arg.rs
@@ -61,12 +61,14 @@
// 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;
diff --git a/src/test/mir-opt/generator-drop-cleanup.rs b/src/test/mir-opt/generator-drop-cleanup.rs
index 30f6d0d..f97e1ba 100644
--- a/src/test/mir-opt/generator-drop-cleanup.rs
+++ b/src/test/mir-opt/generator-drop-cleanup.rs
@@ -18,6 +18,7 @@
// }
// bb1: {
// StorageDead(_3);
+// StorageDead(_2);
// goto -> bb5;
// }
// bb2: {
@@ -36,6 +37,7 @@
// goto -> bb3;
// }
// bb7: {
+// StorageLive(_2);
// StorageLive(_3);
// goto -> bb1;
// }
diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator-storage-dead-unwind.rs
index 7be17c4..bcdb937 100644
--- a/src/test/mir-opt/generator-storage-dead-unwind.rs
+++ b/src/test/mir-opt/generator-storage-dead-unwind.rs
@@ -54,6 +54,7 @@
// }
// bb2: {
// ...
+// StorageLive(_6);
// StorageLive(_7);
// _7 = move _2;
// _6 = const take::<Foo>(move _7) -> [return: bb9, unwind: bb8];
@@ -81,16 +82,20 @@
// }
// 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 @@
// }
// bb11 (cleanup): {
// StorageDead(_9);
+// StorageDead(_8);
// goto -> bb7;
// }
// bb12: {
diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs
index 909f9b7..d980cc8 100644
--- a/src/test/mir-opt/issue-38669.rs
+++ b/src/test/mir-opt/issue-38669.rs
@@ -25,6 +25,7 @@
// falseUnwind -> [real: bb3, cleanup: bb1];
// }
// bb3: {
+// StorageLive(_3);
// StorageLive(_4);
// _4 = _1;
// FakeRead(ForMatchedPlace, _4);
@@ -34,6 +35,7 @@
// bb5: {
// _3 = ();
// StorageDead(_4);
+// StorageDead(_3);
// _1 = const true;
// _2 = ();
// goto -> bb2;
@@ -41,6 +43,7 @@
// bb6: {
// _0 = ();
// StorageDead(_4);
+// StorageDead(_3);
// StorageDead(_1);
// return;
// }
diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs
index 0b678be..e73390f 100644
--- a/src/test/mir-opt/issue-41110.rs
+++ b/src/test/mir-opt/issue-41110.rs
@@ -42,7 +42,7 @@
// 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;
diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs
index 9dde6d8..d0dbcbd 100644
--- a/src/test/mir-opt/issue-49232.rs
+++ b/src/test/mir-opt/issue-49232.rs
@@ -21,7 +21,7 @@
// 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 @@
// 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;
diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs
index 68ea60d..177080c 100644
--- a/src/test/mir-opt/loop_test.rs
+++ b/src/test/mir-opt/loop_test.rs
@@ -25,6 +25,7 @@
// bb3: { // Entry into the loop
// _1 = ();
// StorageDead(_2);
+// StorageDead(_1);
// goto -> bb5;
// }
// ...
diff --git a/src/test/mir-opt/match_test.rs b/src/test/mir-opt/match_test.rs
index ef60a04..aeb1627 100644
--- a/src/test/mir-opt/match_test.rs
+++ b/src/test/mir-opt/match_test.rs
@@ -75,6 +75,7 @@
// goto -> bb14;
// }
// bb14: {
+// StorageDead(_3);
// _0 = ();
// StorageDead(_2);
// StorageDead(_1);
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
index fa0dbe5..8228d97 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic.rs
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -22,9 +22,9 @@
// 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;
diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs
index 6d22e9c..95570ff 100644
--- a/src/test/mir-opt/storage_ranges.rs
+++ b/src/test/mir-opt/storage_ranges.rs
@@ -12,6 +12,7 @@
// StorageLive(_1);
// _1 = const 0i32;
// FakeRead(ForLet, _1);
+// StorageLive(_2);
// StorageLive(_3);
// StorageLive(_4);
// StorageLive(_5);
@@ -23,6 +24,7 @@
// _2 = ();
// StorageDead(_4);
// StorageDead(_3);
+// StorageDead(_2);
// StorageLive(_6);
// _6 = const 1i32;
// FakeRead(ForLet, _6);
diff --git a/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs b/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs
new file mode 100644
index 0000000..ce46420
--- /dev/null
+++ b/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs
@@ -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();
+}