diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 6723fc72a40e..ebf78792d72e 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -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 diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index ca23be7dc061..b4c3e93b2800 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -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() } })); diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index b2c7507ed7b2..be2b70b86990 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -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)); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 7738ebca26b4..661d01ce989c 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -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(); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 4c0e9b98d9a6..a77a64ec3d89 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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: diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 27c374e1ac2c..2041fef885d0 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -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(); diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index a7f4a53b022e..ce2b7dc34ebf 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -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) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 673ff9e86c44..bc92da30caba 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -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); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 41259f8a281d..4bb6b20a5d5b 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -192,7 +192,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { ast_block: &'tcx hir::Block) -> BlockAnd>> { - 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)); } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 6a734e1816a2..1dd9ec5bae5d 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -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(&mut self, extent: CodeExtent, mut block: BasicBlock, f: F) -> BlockAnd - where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd + where F: FnOnce(&mut Builder<'a, 'tcx>, ScopeId) -> BlockAnd { 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() }