record a scope for each VarDecl
This commit is contained in:
parent
464c02e336
commit
323d7f4e98
src
librustc/mir
librustc_mir/build
@ -159,6 +159,8 @@ pub struct VarDecl<'tcx> {
|
||||
pub mutability: Mutability,
|
||||
pub name: Name,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub scope: ScopeId, // scope in which variable was declared
|
||||
pub span: Span, // span where variable was declared
|
||||
}
|
||||
|
||||
/// A "temp" is a temporary that we place on the stack. They are
|
||||
|
@ -20,7 +20,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
ast_block: &'tcx hir::Block)
|
||||
-> BlockAnd<()> {
|
||||
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
|
||||
self.in_scope(extent, block, move |this| {
|
||||
self.in_scope(extent, block, move |this, _| {
|
||||
// This convoluted structure is to avoid using recursion as we walk down a list
|
||||
// of statements. Basically, the structure we get back is something like:
|
||||
//
|
||||
@ -42,7 +42,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let Stmt { span: _, kind } = this.hir.mirror(stmt);
|
||||
match kind {
|
||||
StmtKind::Expr { scope, expr } => {
|
||||
unpack!(block = this.in_scope(scope, block, |this| {
|
||||
unpack!(block = this.in_scope(scope, block, |this, _| {
|
||||
let expr = this.hir.mirror(expr);
|
||||
let temp = this.temp(expr.ty.clone());
|
||||
unpack!(block = this.into(&temp, block, expr));
|
||||
@ -51,14 +51,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}));
|
||||
}
|
||||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
|
||||
this.push_scope(remainder_scope, block);
|
||||
let remainder_scope_id = this.push_scope(remainder_scope, block);
|
||||
let_extent_stack.push(remainder_scope);
|
||||
unpack!(block = this.in_scope(init_scope, block, move |this| {
|
||||
unpack!(block = this.in_scope(init_scope, block, move |this, _| {
|
||||
// FIXME #30046 ^~~~
|
||||
if let Some(init) = initializer {
|
||||
this.expr_into_pattern(block, remainder_scope, pattern, init)
|
||||
this.expr_into_pattern(block, remainder_scope_id, pattern, init)
|
||||
} else {
|
||||
this.declare_bindings(remainder_scope, &pattern);
|
||||
this.declare_bindings(remainder_scope_id, &pattern);
|
||||
block.unit()
|
||||
}
|
||||
}));
|
||||
|
@ -37,7 +37,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let expr_span = expr.span;
|
||||
match expr.kind {
|
||||
ExprKind::Scope { extent, value } => {
|
||||
this.in_scope(extent, block, |this| this.as_lvalue(block, value))
|
||||
this.in_scope(extent, block, |this, _| this.as_lvalue(block, value))
|
||||
}
|
||||
ExprKind::Field { lhs, name } => {
|
||||
let lvalue = unpack!(block = this.as_lvalue(block, lhs));
|
||||
|
@ -35,7 +35,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let this = self;
|
||||
|
||||
if let ExprKind::Scope { extent, value } = expr.kind {
|
||||
return this.in_scope(extent, block, |this| this.as_operand(block, value));
|
||||
return this.in_scope(extent, block, |this, _| this.as_operand(block, value));
|
||||
}
|
||||
|
||||
let category = Category::of(&expr.kind).unwrap();
|
||||
|
@ -37,7 +37,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Scope { extent, value } => {
|
||||
this.in_scope(extent, block, |this| this.as_rvalue(block, value))
|
||||
this.in_scope(extent, block, |this, _| this.as_rvalue(block, value))
|
||||
}
|
||||
ExprKind::InlineAsm { asm, outputs, inputs } => {
|
||||
let outputs = outputs.into_iter().map(|output| {
|
||||
@ -76,7 +76,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let result = this.temp(expr.ty);
|
||||
// to start, malloc some memory of suitable type (thus far, uninitialized):
|
||||
this.cfg.push_assign(block, expr_span, &result, Rvalue::Box(value.ty));
|
||||
this.in_scope(value_extents, block, |this| {
|
||||
this.in_scope(value_extents, block, |this, _| {
|
||||
// schedule a shallow free of that memory, lest we unwind:
|
||||
this.schedule_box_free(expr_span, value_extents, &result, value.ty);
|
||||
// initialize the box contents:
|
||||
|
@ -30,7 +30,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let this = self;
|
||||
|
||||
if let ExprKind::Scope { extent, value } = expr.kind {
|
||||
return this.in_scope(extent, block, |this| this.as_temp(block, value));
|
||||
return this.in_scope(extent, block, |this, _| this.as_temp(block, value));
|
||||
}
|
||||
|
||||
let expr_ty = expr.ty.clone();
|
||||
|
@ -39,7 +39,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Scope { extent, value } => {
|
||||
this.in_scope(extent, block, |this| this.into(destination, block, value))
|
||||
this.in_scope(extent, block, |this, _| this.into(destination, block, value))
|
||||
}
|
||||
ExprKind::Block { body: ast_block } => {
|
||||
this.ast_block(destination, block, ast_block)
|
||||
|
@ -16,7 +16,6 @@
|
||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::middle::ty::{AdtDef, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use hair::*;
|
||||
@ -42,9 +41,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// suitable extent for all of the bindings in this match. It's
|
||||
// easiest to do this up front because some of these arms may
|
||||
// be unreachable or reachable multiple times.
|
||||
let var_extent = self.extent_of_innermost_scope();
|
||||
let var_scope_id = self.innermost_scope_id();
|
||||
for arm in &arms {
|
||||
self.declare_bindings(var_extent, &arm.patterns[0]);
|
||||
self.declare_bindings(var_scope_id, &arm.patterns[0]);
|
||||
}
|
||||
|
||||
let mut arm_blocks = ArmBlocks {
|
||||
@ -106,7 +105,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
pub fn expr_into_pattern(&mut self,
|
||||
mut block: BasicBlock,
|
||||
var_extent: CodeExtent, // lifetime of vars
|
||||
var_scope_id: ScopeId, // lifetime of vars
|
||||
irrefutable_pat: Pattern<'tcx>,
|
||||
initializer: ExprRef<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
@ -118,7 +117,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
var,
|
||||
ty,
|
||||
subpattern: None } => {
|
||||
let index = self.declare_binding(var_extent,
|
||||
let index = self.declare_binding(var_scope_id,
|
||||
mutability,
|
||||
name,
|
||||
var,
|
||||
@ -131,19 +130,19 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
let lvalue = unpack!(block = self.as_lvalue(block, initializer));
|
||||
self.lvalue_into_pattern(block,
|
||||
var_extent,
|
||||
var_scope_id,
|
||||
irrefutable_pat,
|
||||
&lvalue)
|
||||
}
|
||||
|
||||
pub fn lvalue_into_pattern(&mut self,
|
||||
mut block: BasicBlock,
|
||||
var_extent: CodeExtent,
|
||||
var_scope_id: ScopeId,
|
||||
irrefutable_pat: Pattern<'tcx>,
|
||||
initializer: &Lvalue<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
// first, creating the bindings
|
||||
self.declare_bindings(var_extent, &irrefutable_pat);
|
||||
self.declare_bindings(var_scope_id, &irrefutable_pat);
|
||||
|
||||
// create a dummy candidate
|
||||
let mut candidate = Candidate {
|
||||
@ -170,29 +169,29 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
block.unit()
|
||||
}
|
||||
|
||||
pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: &Pattern<'tcx>) {
|
||||
pub fn declare_bindings(&mut self, var_scope_id: ScopeId, pattern: &Pattern<'tcx>) {
|
||||
match *pattern.kind {
|
||||
PatternKind::Binding { mutability, name, mode: _, var, ty, ref subpattern } => {
|
||||
self.declare_binding(var_extent, mutability, name, var, ty, pattern.span);
|
||||
self.declare_binding(var_scope_id, mutability, name, var, ty, pattern.span);
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
self.declare_bindings(var_scope_id, subpattern);
|
||||
}
|
||||
}
|
||||
PatternKind::Array { ref prefix, ref slice, ref suffix } |
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||
for subpattern in prefix.iter().chain(slice).chain(suffix) {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
self.declare_bindings(var_scope_id, subpattern);
|
||||
}
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
|
||||
}
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
self.declare_bindings(var_scope_id, subpattern);
|
||||
}
|
||||
PatternKind::Leaf { ref subpatterns } |
|
||||
PatternKind::Variant { ref subpatterns, .. } => {
|
||||
for subpattern in subpatterns {
|
||||
self.declare_bindings(var_extent, &subpattern.pattern);
|
||||
self.declare_bindings(var_scope_id, &subpattern.pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -590,7 +589,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
|
||||
fn declare_binding(&mut self,
|
||||
var_extent: CodeExtent,
|
||||
var_scope_id: ScopeId,
|
||||
mutability: Mutability,
|
||||
name: Name,
|
||||
var_id: NodeId,
|
||||
@ -598,17 +597,20 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
span: Span)
|
||||
-> u32
|
||||
{
|
||||
debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, var_extent={:?}, span={:?})",
|
||||
var_id, name, var_ty, var_extent, span);
|
||||
debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, var_scope_id={:?}, span={:?})",
|
||||
var_id, name, var_ty, var_scope_id, span);
|
||||
|
||||
let index = self.var_decls.len();
|
||||
self.var_decls.push(VarDecl::<'tcx> {
|
||||
scope: var_scope_id,
|
||||
mutability: mutability,
|
||||
name: name,
|
||||
ty: var_ty.clone(),
|
||||
span: span,
|
||||
});
|
||||
let index = index as u32;
|
||||
self.schedule_drop(span, var_extent, &Lvalue::Var(index), var_ty);
|
||||
let extent = self.scope_auxiliary[var_scope_id.index()].extent;
|
||||
self.schedule_drop(span, extent, &Lvalue::Var(index), var_ty);
|
||||
self.var_indices.insert(var_id, index);
|
||||
|
||||
debug!("declare_binding: index={:?}", index);
|
||||
|
@ -192,7 +192,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
ast_block: &'tcx hir::Block)
|
||||
-> BlockAnd<Vec<ArgDecl<'tcx>>>
|
||||
{
|
||||
self.in_scope(argument_extent, block, |this| {
|
||||
self.in_scope(argument_extent, block, |this, argument_scope_id| {
|
||||
// to start, translate the argument patterns and collect the argument types.
|
||||
let implicits = implicit_arguments.into_iter().map(|ty| (ty, None));
|
||||
let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat)));
|
||||
@ -205,7 +205,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
if let Some(pattern) = pattern {
|
||||
let pattern = this.hir.irrefutable_pat(pattern);
|
||||
unpack!(block = this.lvalue_into_pattern(block,
|
||||
argument_extent,
|
||||
argument_scope_id,
|
||||
pattern,
|
||||
&lvalue));
|
||||
}
|
||||
|
@ -208,11 +208,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// 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, extent: CodeExtent, mut block: BasicBlock, f: F) -> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a, 'tcx>, ScopeId) -> BlockAnd<R>
|
||||
{
|
||||
debug!("in_scope(extent={:?}, block={:?})", extent, block);
|
||||
self.push_scope(extent, block);
|
||||
let rv = unpack!(block = f(self));
|
||||
let id = self.push_scope(extent, block);
|
||||
let rv = unpack!(block = f(self, id));
|
||||
unpack!(block = self.pop_scope(extent, block));
|
||||
debug!("in_scope: exiting extent={:?} block={:?}", extent, block);
|
||||
block.and(rv)
|
||||
@ -222,7 +222,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// scope and call `pop_scope` afterwards. Note that these two
|
||||
/// calls must be paired; using `in_scope` as a convenience
|
||||
/// wrapper maybe preferable.
|
||||
pub fn push_scope(&mut self, extent: CodeExtent, entry: BasicBlock) {
|
||||
pub fn push_scope(&mut self, extent: CodeExtent, entry: BasicBlock) -> ScopeId {
|
||||
debug!("push_scope({:?})", extent);
|
||||
let parent_id = self.scopes.last().map(|s| s.id);
|
||||
let id = ScopeId::new(self.scope_data_vec.vec.len());
|
||||
@ -240,6 +240,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
dom: self.cfg.current_location(entry),
|
||||
postdoms: vec![]
|
||||
});
|
||||
id
|
||||
}
|
||||
|
||||
/// Pops a scope, which should have extent `extent`, adding any
|
||||
@ -321,6 +322,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}.unwrap_or_else(|| hir.span_bug(span, "no enclosing loop scope found?"))
|
||||
}
|
||||
|
||||
pub fn innermost_scope_id(&self) -> ScopeId {
|
||||
self.scopes.last().map(|scope| scope.id).unwrap()
|
||||
}
|
||||
|
||||
pub fn extent_of_innermost_scope(&self) -> CodeExtent {
|
||||
self.scopes.last().map(|scope| scope.extent).unwrap()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user