For diagnostics, set spans of drops of temps to be that of the statement's terminating semicolon.

This commit is contained in:
Felix S. Klock II 2018-11-08 11:37:27 +01:00
parent 1d834550d5
commit ece4f472c9
6 changed files with 33 additions and 7 deletions

View File

@ -90,7 +90,7 @@ fn ast_block_stmts(&mut self,
let source_info = this.source_info(span);
for stmt in stmts {
let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
let Stmt { kind, opt_destruction_scope, span: stmt_span } = this.hir.mirror(stmt);
match kind {
StmtKind::Expr { scope, expr } => {
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
@ -99,7 +99,7 @@ fn ast_block_stmts(&mut self,
let si = (scope, source_info);
this.in_scope(si, LintLevel::Inherited, block, |this| {
let expr = this.hir.mirror(expr);
this.stmt_expr(block, expr)
this.stmt_expr(block, expr, Some(stmt_span))
})
}));
}

View File

@ -351,7 +351,7 @@ fn expr_as_rvalue(
block.and(Rvalue::Aggregate(adt, fields))
}
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
block = unpack!(this.stmt_expr(block, expr));
block = unpack!(this.stmt_expr(block, expr, None));
block.and(this.unit_rvalue())
}
ExprKind::Yield { value } => {

View File

@ -351,7 +351,7 @@ pub fn into_expr(
| ExprKind::Break { .. }
| ExprKind::InlineAsm { .. }
| ExprKind::Return { .. } => {
unpack!(block = this.stmt_expr(block, expr));
unpack!(block = this.stmt_expr(block, expr, None));
this.cfg.push_assign_unit(block, source_info, destination);
block.unit()
}

View File

@ -14,7 +14,18 @@
use rustc::mir::*;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<()> {
/// Builds a block of MIR statements to evaluate the HAIR `expr`.
/// 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<()>
{
let this = self;
let expr_span = expr.span;
let source_info = this.source_info(expr.span);
@ -29,7 +40,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
} => {
let value = this.hir.mirror(value);
this.in_scope((region_scope, source_info), lint_level, block, |this| {
this.stmt_expr(block, value)
this.stmt_expr(block, value, opt_stmt_span)
})
}
ExprKind::Assign { lhs, rhs } => {
@ -192,7 +203,15 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
let expr_ty = expr.ty;
let temp = this.temp(expr.ty.clone(), expr_span);
unpack!(block = this.into(&temp, block, expr));
unpack!(block = this.build_drop(block, expr_span, temp, expr_ty));
// 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,
});
unpack!(block = this.build_drop(block, drop_point, temp, expr_ty));
block.unit()
}
}

View File

@ -57,6 +57,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
for (index, stmt) in stmts.iter().enumerate() {
let hir_id = cx.tcx.hir.node_to_hir_id(stmt.node.id());
let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
let stmt_span = StatementSpan(cx.tcx.hir.span(stmt.node.id()));
match stmt.node {
hir::StmtKind::Expr(ref expr, _) |
hir::StmtKind::Semi(ref expr, _) => {
@ -69,6 +70,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: expr.to_ref(),
},
opt_destruction_scope: opt_dxn_ext,
span: stmt_span,
})))
}
hir::StmtKind::Decl(ref decl, _) => {
@ -111,6 +113,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
lint_level: cx.lint_level_of(local.id),
},
opt_destruction_scope: opt_dxn_ext,
span: stmt_span,
})));
}
}

View File

@ -71,10 +71,14 @@ pub enum StmtRef<'tcx> {
Mirror(Box<Stmt<'tcx>>),
}
#[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)]