mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 10:45:18 +00:00
Add destruction extents around blocks and statements in HAIR.
This commit is contained in:
parent
609813bbc2
commit
cbed41a174
@ -21,21 +21,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ast_block: &'tcx hir::Block,
|
||||
source_info: SourceInfo)
|
||||
-> BlockAnd<()> {
|
||||
let Block { extent, span, stmts, expr, targeted_by_break } = self.hir.mirror(ast_block);
|
||||
self.in_scope(extent, block, move |this| {
|
||||
if targeted_by_break {
|
||||
// This is a `break`-able block (currently only `catch { ... }`)
|
||||
let exit_block = this.cfg.start_new_block();
|
||||
let block_exit = this.in_breakable_scope(None, exit_block,
|
||||
destination.clone(), |this| {
|
||||
let Block { extent, opt_destruction_extent, span, stmts, expr, targeted_by_break } =
|
||||
self.hir.mirror(ast_block);
|
||||
self.in_opt_scope(opt_destruction_extent, block, move |this| {
|
||||
this.in_scope(extent, block, move |this| {
|
||||
if targeted_by_break {
|
||||
// This is a `break`-able block (currently only `catch { ... }`)
|
||||
let exit_block = this.cfg.start_new_block();
|
||||
let block_exit = this.in_breakable_scope(
|
||||
None, exit_block, destination.clone(), |this| {
|
||||
this.ast_block_stmts(destination, block, span, stmts, expr)
|
||||
});
|
||||
this.cfg.terminate(unpack!(block_exit), source_info,
|
||||
TerminatorKind::Goto { target: exit_block });
|
||||
exit_block.unit()
|
||||
} else {
|
||||
this.ast_block_stmts(destination, block, span, stmts, expr)
|
||||
});
|
||||
this.cfg.terminate(unpack!(block_exit), source_info,
|
||||
TerminatorKind::Goto { target: exit_block });
|
||||
exit_block.unit()
|
||||
} else {
|
||||
this.ast_block_stmts(destination, block, span, stmts, expr)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -67,12 +70,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let mut let_extent_stack = Vec::with_capacity(8);
|
||||
let outer_visibility_scope = this.visibility_scope;
|
||||
for stmt in stmts {
|
||||
let Stmt { span: _, kind } = this.hir.mirror(stmt);
|
||||
let Stmt { span: _, kind, opt_destruction_extent } = this.hir.mirror(stmt);
|
||||
match kind {
|
||||
StmtKind::Expr { scope, expr } => {
|
||||
unpack!(block = this.in_scope(scope, block, |this| {
|
||||
let expr = this.hir.mirror(expr);
|
||||
this.stmt_expr(block, expr)
|
||||
unpack!(block = this.in_opt_scope(opt_destruction_extent, block, |this| {
|
||||
this.in_scope(scope, block, |this| {
|
||||
let expr = this.hir.mirror(expr);
|
||||
this.stmt_expr(block, expr)
|
||||
})
|
||||
}));
|
||||
}
|
||||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
|
||||
@ -89,10 +94,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Evaluate the initializer, if present.
|
||||
if let Some(init) = initializer {
|
||||
unpack!(block = this.in_scope(init_scope, block, move |this| {
|
||||
// FIXME #30046 ^~~~
|
||||
this.expr_into_pattern(block, pattern, init)
|
||||
}));
|
||||
unpack!(block = this.in_opt_scope(
|
||||
opt_destruction_extent, block, move |this| {
|
||||
this.in_scope(init_scope, block, move |this| {
|
||||
// FIXME #30046 ^~~~
|
||||
this.expr_into_pattern(block, pattern, init)
|
||||
})
|
||||
}));
|
||||
} else {
|
||||
this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
|
||||
this.storage_live_binding(block, node, span);
|
||||
|
@ -269,6 +269,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
res
|
||||
}
|
||||
|
||||
pub fn in_opt_scope<F, R>(&mut self,
|
||||
opt_extent: Option<CodeExtent>,
|
||||
mut block: BasicBlock,
|
||||
f: F)
|
||||
-> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
|
||||
{
|
||||
debug!("in_opt_scope(opt_extent={:?}, block={:?})", opt_extent, block);
|
||||
if let Some(extent) = opt_extent { self.push_scope(extent); }
|
||||
let rv = unpack!(block = f(self));
|
||||
if let Some(extent) = opt_extent {
|
||||
unpack!(block = self.pop_scope(extent, block));
|
||||
}
|
||||
debug!("in_scope: exiting opt_extent={:?} block={:?}", opt_extent, block);
|
||||
block.and(rv)
|
||||
}
|
||||
|
||||
/// Convenience wrapper that pushes a scope and then executes `f`
|
||||
/// to build its contents, popping the scope afterwards.
|
||||
pub fn in_scope<F, R>(&mut self,
|
||||
|
@ -22,9 +22,14 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
|
||||
// We have to eagerly translate the "spine" of the statements
|
||||
// in order to get the lexical scoping correctly.
|
||||
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
|
||||
let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id);
|
||||
let opt_destruction_extent = opt_def_id.and_then(|def_id| {
|
||||
cx.tcx.region_maps(def_id).opt_destruction_extent(self.id)
|
||||
});
|
||||
Block {
|
||||
targeted_by_break: self.targeted_by_break,
|
||||
extent: CodeExtent::Misc(self.id),
|
||||
opt_destruction_extent: opt_destruction_extent,
|
||||
span: self.span,
|
||||
stmts: stmts,
|
||||
expr: self.expr.to_ref(),
|
||||
@ -37,7 +42,11 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
stmts: &'tcx [hir::Stmt])
|
||||
-> Vec<StmtRef<'tcx>> {
|
||||
let mut result = vec![];
|
||||
let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id);
|
||||
for (index, stmt) in stmts.iter().enumerate() {
|
||||
let opt_dxn_ext = opt_def_id.and_then(|def_id| {
|
||||
cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id())
|
||||
});
|
||||
match stmt.node {
|
||||
hir::StmtExpr(ref expr, id) |
|
||||
hir::StmtSemi(ref expr, id) => {
|
||||
@ -47,6 +56,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
scope: CodeExtent::Misc(id),
|
||||
expr: expr.to_ref(),
|
||||
},
|
||||
opt_destruction_extent: opt_dxn_ext,
|
||||
})))
|
||||
}
|
||||
hir::StmtDecl(ref decl, id) => {
|
||||
@ -69,6 +79,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
pattern: pattern,
|
||||
initializer: local.init.to_ref(),
|
||||
},
|
||||
opt_destruction_extent: opt_dxn_ext,
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPatt
|
||||
pub struct Block<'tcx> {
|
||||
pub targeted_by_break: bool,
|
||||
pub extent: CodeExtent,
|
||||
pub opt_destruction_extent: Option<CodeExtent>,
|
||||
pub span: Span,
|
||||
pub stmts: Vec<StmtRef<'tcx>>,
|
||||
pub expr: Option<ExprRef<'tcx>>,
|
||||
@ -47,6 +48,7 @@ pub enum StmtRef<'tcx> {
|
||||
pub struct Stmt<'tcx> {
|
||||
pub span: Span,
|
||||
pub kind: StmtKind<'tcx>,
|
||||
pub opt_destruction_extent: Option<CodeExtent>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
Loading…
Reference in New Issue
Block a user