record a scope for each VarDecl

This commit is contained in:
Niko Matsakis 2016-03-09 12:36:07 -05:00
parent 464c02e336
commit 323d7f4e98
10 changed files with 45 additions and 36 deletions

@ -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()
}