Use as_temp
to evaluate statement expressions
This commit is contained in:
parent
62bec71446
commit
101a2f59b4
17 changed files with 96 additions and 81 deletions
|
@ -78,7 +78,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
let source_info = this.source_info(span);
|
let source_info = this.source_info(span);
|
||||||
for stmt in stmts {
|
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 {
|
match kind {
|
||||||
StmtKind::Expr { scope, expr } => {
|
StmtKind::Expr { scope, expr } => {
|
||||||
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
|
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
|
||||||
|
@ -87,7 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let si = (scope, source_info);
|
let si = (scope, source_info);
|
||||||
this.in_scope(si, LintLevel::Inherited, |this| {
|
this.in_scope(si, LintLevel::Inherited, |this| {
|
||||||
let expr = this.hir.mirror(expr);
|
let expr = this.hir.mirror(expr);
|
||||||
this.stmt_expr(block, expr, Some(stmt_span))
|
this.stmt_expr(block, expr, Some(scope))
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::build::scope::BreakableScope;
|
use crate::build::scope::BreakableScope;
|
||||||
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
||||||
use crate::hair::*;
|
use crate::hair::*;
|
||||||
|
use rustc::middle::region;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
@ -8,14 +9,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// If the original expression was an AST statement,
|
/// If the original expression was an AST statement,
|
||||||
/// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
|
/// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
|
||||||
/// span of that statement (including its semicolon, if any).
|
/// span of that statement (including its semicolon, if any).
|
||||||
/// Diagnostics use this span (which may be larger than that of
|
/// The scope is used if a statement temporary must be dropped.
|
||||||
/// `expr`) to identify when statement temporaries are dropped.
|
pub fn stmt_expr(
|
||||||
pub fn stmt_expr(&mut self,
|
&mut self,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
expr: Expr<'tcx>,
|
expr: Expr<'tcx>,
|
||||||
opt_stmt_span: Option<StatementSpan>)
|
statement_scope: Option<region::Scope>,
|
||||||
-> BlockAnd<()>
|
) -> BlockAnd<()> {
|
||||||
{
|
|
||||||
let this = self;
|
let this = self;
|
||||||
let expr_span = expr.span;
|
let expr_span = expr.span;
|
||||||
let source_info = this.source_info(expr.span);
|
let source_info = this.source_info(expr.span);
|
||||||
|
@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
} => {
|
} => {
|
||||||
let value = this.hir.mirror(value);
|
let value = this.hir.mirror(value);
|
||||||
this.in_scope((region_scope, source_info), lint_level, |this| {
|
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 } => {
|
ExprKind::Assign { lhs, rhs } => {
|
||||||
|
@ -199,7 +199,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.unit()
|
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
|
// Issue #54382: When creating temp for the value of
|
||||||
// expression like:
|
// expression like:
|
||||||
|
@ -208,48 +212,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
//
|
//
|
||||||
// it is usually better to focus on `the_value` rather
|
// it is usually better to focus on `the_value` rather
|
||||||
// than the entirety of block(s) surrounding it.
|
// than the entirety of block(s) surrounding it.
|
||||||
let mut temp_span = expr_span;
|
let adjusted_span = (|| {
|
||||||
let mut temp_in_tail_of_block = false;
|
if let ExprKind::Block { body } = expr.kind {
|
||||||
if let ExprKind::Block { body } = expr.kind {
|
if let Some(tail_expr) = &body.expr {
|
||||||
if let Some(tail_expr) = &body.expr {
|
let mut expr = tail_expr;
|
||||||
let mut expr = tail_expr;
|
while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
|
||||||
while let rustc::hir::ExprKind::Block(subblock, _label) = &expr.node {
|
if let Some(subtail_expr) = &subblock.expr {
|
||||||
if let Some(subtail_expr) = &subblock.expr {
|
expr = subtail_expr
|
||||||
expr = subtail_expr
|
} else {
|
||||||
} else {
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
this.block_context.push(BlockFrame::TailExpr {
|
||||||
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 {
|
|
||||||
tail_result_is_ignored: true
|
tail_result_is_ignored: true
|
||||||
});
|
});
|
||||||
|
return Some(expr.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let temp = this.local_decls.push(local_decl);
|
None
|
||||||
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));
|
|
||||||
|
|
||||||
// Attribute drops of the statement's temps to the
|
let temp = unpack!(block =
|
||||||
// semicolon at the statement's end.
|
this.as_temp(block, statement_scope, expr, Mutability::Not));
|
||||||
let drop_point = this.hir.tcx().sess.source_map().end_point(match opt_stmt_span {
|
|
||||||
None => expr_span,
|
if let Some(span) = adjusted_span {
|
||||||
Some(StatementSpan(span)) => span,
|
this.local_decls[temp].source_info.span = span;
|
||||||
});
|
this.block_context.pop();
|
||||||
|
}
|
||||||
|
|
||||||
unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
|
|
||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -805,27 +805,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
target
|
target
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
/// Utility function for *non*-scope code to build their own drops
|
||||||
pub fn build_drop_and_replace(&mut self,
|
pub fn build_drop_and_replace(&mut self,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
|
|
|
@ -49,7 +49,6 @@ fn mirror_stmts<'a, 'tcx>(
|
||||||
for (index, stmt) in stmts.iter().enumerate() {
|
for (index, stmt) in stmts.iter().enumerate() {
|
||||||
let hir_id = stmt.hir_id;
|
let hir_id = stmt.hir_id;
|
||||||
let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_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 {
|
match stmt.node {
|
||||||
hir::StmtKind::Expr(ref expr) |
|
hir::StmtKind::Expr(ref expr) |
|
||||||
hir::StmtKind::Semi(ref expr) => {
|
hir::StmtKind::Semi(ref expr) => {
|
||||||
|
@ -62,7 +61,6 @@ fn mirror_stmts<'a, 'tcx>(
|
||||||
expr: expr.to_ref(),
|
expr: expr.to_ref(),
|
||||||
},
|
},
|
||||||
opt_destruction_scope: opt_dxn_ext,
|
opt_destruction_scope: opt_dxn_ext,
|
||||||
span: stmt_span,
|
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
hir::StmtKind::Item(..) => {
|
hir::StmtKind::Item(..) => {
|
||||||
|
@ -107,7 +105,6 @@ fn mirror_stmts<'a, 'tcx>(
|
||||||
lint_level: LintLevel::Explicit(local.hir_id),
|
lint_level: LintLevel::Explicit(local.hir_id),
|
||||||
},
|
},
|
||||||
opt_destruction_scope: opt_dxn_ext,
|
opt_destruction_scope: opt_dxn_ext,
|
||||||
span: stmt_span,
|
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,14 +55,10 @@ pub enum StmtRef<'tcx> {
|
||||||
Mirror(Box<Stmt<'tcx>>),
|
Mirror(Box<Stmt<'tcx>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct StatementSpan(pub Span);
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Stmt<'tcx> {
|
pub struct Stmt<'tcx> {
|
||||||
pub kind: StmtKind<'tcx>,
|
pub kind: StmtKind<'tcx>,
|
||||||
pub opt_destruction_scope: Option<region::Scope>,
|
pub opt_destruction_scope: Option<region::Scope>,
|
||||||
pub span: StatementSpan,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -24,7 +24,7 @@ impl Drop for S {
|
||||||
// let mut _0: ();
|
// let mut _0: ();
|
||||||
// let _1: std::boxed::Box<S>;
|
// let _1: std::boxed::Box<S>;
|
||||||
// let mut _2: std::boxed::Box<S>;
|
// let mut _2: std::boxed::Box<S>;
|
||||||
// let mut _3: ();
|
// let _3: ();
|
||||||
// let mut _4: std::boxed::Box<S>;
|
// let mut _4: std::boxed::Box<S>;
|
||||||
// scope 1 {
|
// scope 1 {
|
||||||
// }
|
// }
|
||||||
|
@ -50,6 +50,7 @@ impl Drop for S {
|
||||||
//
|
//
|
||||||
// bb4: {
|
// bb4: {
|
||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
|
// StorageLive(_3);
|
||||||
// StorageLive(_4);
|
// StorageLive(_4);
|
||||||
// _4 = move _1;
|
// _4 = move _1;
|
||||||
// _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
|
// _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
|
||||||
|
@ -69,6 +70,7 @@ impl Drop for S {
|
||||||
//
|
//
|
||||||
// bb8: {
|
// bb8: {
|
||||||
// StorageDead(_4);
|
// StorageDead(_4);
|
||||||
|
// StorageDead(_3);
|
||||||
// _0 = ();
|
// _0 = ();
|
||||||
// drop(_1) -> bb9;
|
// drop(_1) -> bb9;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -61,12 +61,14 @@ fn main() {
|
||||||
// END rustc.foo.CopyPropagation.after.mir
|
// END rustc.foo.CopyPropagation.after.mir
|
||||||
// START rustc.bar.CopyPropagation.before.mir
|
// START rustc.bar.CopyPropagation.before.mir
|
||||||
// bb0: {
|
// bb0: {
|
||||||
|
// StorageLive(_2);
|
||||||
// StorageLive(_3);
|
// StorageLive(_3);
|
||||||
// _3 = _1;
|
// _3 = _1;
|
||||||
// _2 = const dummy(move _3) -> bb1;
|
// _2 = const dummy(move _3) -> bb1;
|
||||||
// }
|
// }
|
||||||
// bb1: {
|
// bb1: {
|
||||||
// StorageDead(_3);
|
// StorageDead(_3);
|
||||||
|
// StorageDead(_2);
|
||||||
// _1 = const 5u8;
|
// _1 = const 5u8;
|
||||||
// ...
|
// ...
|
||||||
// return;
|
// return;
|
||||||
|
|
|
@ -18,6 +18,7 @@ fn main() {
|
||||||
// }
|
// }
|
||||||
// bb1: {
|
// bb1: {
|
||||||
// StorageDead(_3);
|
// StorageDead(_3);
|
||||||
|
// StorageDead(_2);
|
||||||
// goto -> bb5;
|
// goto -> bb5;
|
||||||
// }
|
// }
|
||||||
// bb2: {
|
// bb2: {
|
||||||
|
@ -36,6 +37,7 @@ fn main() {
|
||||||
// goto -> bb3;
|
// goto -> bb3;
|
||||||
// }
|
// }
|
||||||
// bb7: {
|
// bb7: {
|
||||||
|
// StorageLive(_2);
|
||||||
// StorageLive(_3);
|
// StorageLive(_3);
|
||||||
// goto -> bb1;
|
// goto -> bb1;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -54,6 +54,7 @@ fn main() {
|
||||||
// }
|
// }
|
||||||
// bb2: {
|
// bb2: {
|
||||||
// ...
|
// ...
|
||||||
|
// StorageLive(_6);
|
||||||
// StorageLive(_7);
|
// StorageLive(_7);
|
||||||
// _7 = move _2;
|
// _7 = move _2;
|
||||||
// _6 = const take::<Foo>(move _7) -> [return: bb9, unwind: bb8];
|
// _6 = const take::<Foo>(move _7) -> [return: bb9, unwind: bb8];
|
||||||
|
@ -81,16 +82,20 @@ fn main() {
|
||||||
// }
|
// }
|
||||||
// bb8 (cleanup): {
|
// bb8 (cleanup): {
|
||||||
// StorageDead(_7);
|
// StorageDead(_7);
|
||||||
|
// StorageDead(_6);
|
||||||
// goto -> bb7;
|
// goto -> bb7;
|
||||||
// }
|
// }
|
||||||
// bb9: {
|
// bb9: {
|
||||||
// StorageDead(_7);
|
// StorageDead(_7);
|
||||||
|
// StorageDead(_6);
|
||||||
|
// StorageLive(_8);
|
||||||
// StorageLive(_9);
|
// StorageLive(_9);
|
||||||
// _9 = move _3;
|
// _9 = move _3;
|
||||||
// _8 = const take::<Bar>(move _9) -> [return: bb10, unwind: bb11];
|
// _8 = const take::<Bar>(move _9) -> [return: bb10, unwind: bb11];
|
||||||
// }
|
// }
|
||||||
// bb10: {
|
// bb10: {
|
||||||
// StorageDead(_9);
|
// StorageDead(_9);
|
||||||
|
// StorageDead(_8);
|
||||||
// ...
|
// ...
|
||||||
// StorageDead(_3);
|
// StorageDead(_3);
|
||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
|
@ -98,6 +103,7 @@ fn main() {
|
||||||
// }
|
// }
|
||||||
// bb11 (cleanup): {
|
// bb11 (cleanup): {
|
||||||
// StorageDead(_9);
|
// StorageDead(_9);
|
||||||
|
// StorageDead(_8);
|
||||||
// goto -> bb7;
|
// goto -> bb7;
|
||||||
// }
|
// }
|
||||||
// bb12: {
|
// bb12: {
|
||||||
|
|
|
@ -25,6 +25,7 @@ fn main() {
|
||||||
// falseUnwind -> [real: bb3, cleanup: bb1];
|
// falseUnwind -> [real: bb3, cleanup: bb1];
|
||||||
// }
|
// }
|
||||||
// bb3: {
|
// bb3: {
|
||||||
|
// StorageLive(_3);
|
||||||
// StorageLive(_4);
|
// StorageLive(_4);
|
||||||
// _4 = _1;
|
// _4 = _1;
|
||||||
// FakeRead(ForMatchedPlace, _4);
|
// FakeRead(ForMatchedPlace, _4);
|
||||||
|
@ -34,6 +35,7 @@ fn main() {
|
||||||
// bb5: {
|
// bb5: {
|
||||||
// _3 = ();
|
// _3 = ();
|
||||||
// StorageDead(_4);
|
// StorageDead(_4);
|
||||||
|
// StorageDead(_3);
|
||||||
// _1 = const true;
|
// _1 = const true;
|
||||||
// _2 = ();
|
// _2 = ();
|
||||||
// goto -> bb2;
|
// goto -> bb2;
|
||||||
|
@ -41,6 +43,7 @@ fn main() {
|
||||||
// bb6: {
|
// bb6: {
|
||||||
// _0 = ();
|
// _0 = ();
|
||||||
// StorageDead(_4);
|
// StorageDead(_4);
|
||||||
|
// StorageDead(_3);
|
||||||
// StorageDead(_1);
|
// StorageDead(_1);
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl S {
|
||||||
// START rustc.test.ElaborateDrops.after.mir
|
// START rustc.test.ElaborateDrops.after.mir
|
||||||
// let mut _0: ();
|
// let mut _0: ();
|
||||||
// let _1: S;
|
// let _1: S;
|
||||||
// let mut _3: ();
|
// let _3: ();
|
||||||
// let mut _4: S;
|
// let mut _4: S;
|
||||||
// let mut _5: S;
|
// let mut _5: S;
|
||||||
// let mut _6: bool;
|
// let mut _6: bool;
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn main() {
|
||||||
// let _2: i32;
|
// let _2: i32;
|
||||||
// let mut _3: bool;
|
// let mut _3: bool;
|
||||||
// let mut _4: !;
|
// let mut _4: !;
|
||||||
// let mut _5: ();
|
// let _5: ();
|
||||||
// let mut _6: &i32;
|
// let mut _6: &i32;
|
||||||
// scope 1 {
|
// scope 1 {
|
||||||
// }
|
// }
|
||||||
|
@ -73,12 +73,14 @@ fn main() {
|
||||||
// bb12: {
|
// bb12: {
|
||||||
// FakeRead(ForLet, _2);
|
// FakeRead(ForLet, _2);
|
||||||
// StorageDead(_3);
|
// StorageDead(_3);
|
||||||
|
// StorageLive(_5);
|
||||||
// StorageLive(_6);
|
// StorageLive(_6);
|
||||||
// _6 = &_2;
|
// _6 = &_2;
|
||||||
// _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb4];
|
// _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb4];
|
||||||
// }
|
// }
|
||||||
// bb13: {
|
// bb13: {
|
||||||
// StorageDead(_6);
|
// StorageDead(_6);
|
||||||
|
// StorageDead(_5);
|
||||||
// _1 = ();
|
// _1 = ();
|
||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
// goto -> bb1;
|
// goto -> bb1;
|
||||||
|
|
|
@ -25,6 +25,7 @@ fn main() {
|
||||||
// bb3: { // Entry into the loop
|
// bb3: { // Entry into the loop
|
||||||
// _1 = ();
|
// _1 = ();
|
||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
|
// StorageDead(_1);
|
||||||
// goto -> bb5;
|
// goto -> bb5;
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -75,6 +75,7 @@ fn main() {
|
||||||
// goto -> bb14;
|
// goto -> bb14;
|
||||||
// }
|
// }
|
||||||
// bb14: {
|
// bb14: {
|
||||||
|
// StorageDead(_3);
|
||||||
// _0 = ();
|
// _0 = ();
|
||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
// StorageDead(_1);
|
// StorageDead(_1);
|
||||||
|
|
|
@ -22,9 +22,9 @@ fn main() {
|
||||||
|
|
||||||
// END RUST SOURCE
|
// END RUST SOURCE
|
||||||
// START rustc.main.nll.0.mir
|
// START rustc.main.nll.0.mir
|
||||||
// | '_#2r | U0 | {bb2[0..=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..=1]}
|
// | '_#3r | U0 | {bb2[1..=8], bb3[0], bb5[0..=2]}
|
||||||
// | '_#4r | U0 | {bb2[4..=8], bb3[0], bb5[0..=1]}
|
// | '_#4r | U0 | {bb2[4..=8], bb3[0], bb5[0..=2]}
|
||||||
// END rustc.main.nll.0.mir
|
// END rustc.main.nll.0.mir
|
||||||
// START rustc.main.nll.0.mir
|
// START rustc.main.nll.0.mir
|
||||||
// let _2: &'_#3r usize;
|
// let _2: &'_#3r usize;
|
||||||
|
|
|
@ -12,6 +12,7 @@ fn main() {
|
||||||
// StorageLive(_1);
|
// StorageLive(_1);
|
||||||
// _1 = const 0i32;
|
// _1 = const 0i32;
|
||||||
// FakeRead(ForLet, _1);
|
// FakeRead(ForLet, _1);
|
||||||
|
// StorageLive(_2);
|
||||||
// StorageLive(_3);
|
// StorageLive(_3);
|
||||||
// StorageLive(_4);
|
// StorageLive(_4);
|
||||||
// StorageLive(_5);
|
// StorageLive(_5);
|
||||||
|
@ -23,6 +24,7 @@ fn main() {
|
||||||
// _2 = ();
|
// _2 = ();
|
||||||
// StorageDead(_4);
|
// StorageDead(_4);
|
||||||
// StorageDead(_3);
|
// StorageDead(_3);
|
||||||
|
// StorageDead(_2);
|
||||||
// StorageLive(_6);
|
// StorageLive(_6);
|
||||||
// _6 = const 1i32;
|
// _6 = const 1i32;
|
||||||
// FakeRead(ForLet, _6);
|
// FakeRead(ForLet, _6);
|
||||||
|
|
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();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue