diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1ea6c461fc180..cf3d7c3642a5f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -901,10 +901,10 @@ pub enum StatementKind<'tcx> { SetDiscriminant { lvalue: Lvalue<'tcx>, variant_index: usize }, /// Start a live range for the storage of the local. - StorageLive(Lvalue<'tcx>), + StorageLive(Local), /// End the current live range for the storage of the local. - StorageDead(Lvalue<'tcx>), + StorageDead(Local), /// Execute a piece of inline Assembly. InlineAsm { @@ -1077,12 +1077,12 @@ pub enum ProjectionElem<'tcx, V, T> { } /// Alias for projections as they appear in lvalues, where the base is an lvalue -/// and the index is an operand. -pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Operand<'tcx>, Ty<'tcx>>; +/// and the index is a local. +pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx>>; /// Alias for projections as they appear in lvalues, where the base is an lvalue -/// and the index is an operand. -pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Operand<'tcx>, Ty<'tcx>>; +/// and the index is a local. +pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>; newtype_index!(Field, "field"); @@ -1099,7 +1099,7 @@ impl<'tcx> Lvalue<'tcx> { self.elem(ProjectionElem::Downcast(adt_def, variant_index)) } - pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> { + pub fn index(self, index: Local) -> Lvalue<'tcx> { self.elem(ProjectionElem::Index(index)) } @@ -1701,8 +1701,8 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { lvalue: lvalue.fold_with(folder), variant_index, }, - StorageLive(ref lval) => StorageLive(lval.fold_with(folder)), - StorageDead(ref lval) => StorageDead(lval.fold_with(folder)), + StorageLive(ref local) => StorageLive(local.fold_with(folder)), + StorageDead(ref local) => StorageDead(local.fold_with(folder)), InlineAsm { ref asm, ref outputs, ref inputs } => InlineAsm { asm: asm.clone(), outputs: outputs.fold_with(folder), @@ -1732,9 +1732,9 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { match self.kind { Assign(ref lval, ref rval) => { lval.visit_with(visitor) || rval.visit_with(visitor) } - SetDiscriminant { ref lvalue, .. } | - StorageLive(ref lvalue) | - StorageDead(ref lvalue) => lvalue.visit_with(visitor), + SetDiscriminant { ref lvalue, .. } => lvalue.visit_with(visitor), + StorageLive(ref local) | + StorageDead(ref local) => local.visit_with(visitor), InlineAsm { ref outputs, ref inputs, .. } => outputs.visit_with(visitor) || inputs.visit_with(visitor), diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 6589e824187fd..f26505c6d0237 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -256,7 +256,9 @@ macro_rules! make_mir_visitor { } fn visit_local(&mut self, - _local: & $($mutability)* Local) { + _local: & $($mutability)* Local, + _context: LvalueContext<'tcx>, + _location: Location) { } fn visit_visibility_scope(&mut self, @@ -358,11 +360,11 @@ macro_rules! make_mir_visitor { StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => { self.visit_lvalue(lvalue, LvalueContext::Store, location); } - StatementKind::StorageLive(ref $($mutability)* lvalue) => { - self.visit_lvalue(lvalue, LvalueContext::StorageLive, location); + StatementKind::StorageLive(ref $($mutability)* local) => { + self.visit_local(local, LvalueContext::StorageLive, location); } - StatementKind::StorageDead(ref $($mutability)* lvalue) => { - self.visit_lvalue(lvalue, LvalueContext::StorageDead, location); + StatementKind::StorageDead(ref $($mutability)* local) => { + self.visit_local(local, LvalueContext::StorageDead, location); } StatementKind::InlineAsm { ref $($mutability)* outputs, ref $($mutability)* inputs, @@ -610,7 +612,7 @@ macro_rules! make_mir_visitor { location: Location) { match *lvalue { Lvalue::Local(ref $($mutability)* local) => { - self.visit_local(local); + self.visit_local(local, context, location); } Lvalue::Static(ref $($mutability)* static_) => { self.visit_static(static_, context, location); @@ -662,8 +664,8 @@ macro_rules! make_mir_visitor { ProjectionElem::Field(_field, ref $($mutability)* ty) => { self.visit_ty(ty, Lookup::Loc(location)); } - ProjectionElem::Index(ref $($mutability)* operand) => { - self.visit_operand(operand, location); + ProjectionElem::Index(ref $($mutability)* local) => { + self.visit_local(local, LvalueContext::Consume, location); } ProjectionElem::ConstantIndex { offset: _, min_length: _, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index ae05568ab4148..44b505e19658f 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -421,7 +421,7 @@ macro_rules! CopyImpls { } } -CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId } +CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId, ::mir::Local } impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) { diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index af550aea07ee9..063cbc7755915 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -212,11 +212,11 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> // ignored by borrowck } - StatementKind::StorageDead(ref lvalue) => { + StatementKind::StorageDead(local) => { // causes non-drop values to be dropped. self.consume_lvalue(ContextKind::StorageDead.new(location), ConsumeKind::Consume, - (lvalue, span), + (&Lvalue::Local(local), span), flow_state) } } @@ -710,7 +710,7 @@ mod restrictions { use rustc::hir; use rustc::ty::{self, TyCtxt}; - use rustc::mir::{Lvalue, Mir, Operand, ProjectionElem}; + use rustc::mir::{Lvalue, Mir, ProjectionElem}; pub(super) struct Restrictions<'c, 'tcx: 'c> { mir: &'c Mir<'tcx>, @@ -809,12 +809,7 @@ mod restrictions { ProjectionElem::Downcast(..) | ProjectionElem::Subslice { .. } | ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Index(Operand::Constant(..)) => { - cursor = &proj.base; - continue 'cursor; - } - ProjectionElem::Index(Operand::Consume(ref index)) => { - self.lvalue_stack.push(index); // FIXME: did old borrowck do this? + ProjectionElem::Index(_) => { cursor = &proj.base; continue 'cursor; } @@ -1004,7 +999,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> ("", format!(""), None), // (dont emit downcast info) ProjectionElem::Field(field, _ty) => ("", format!(".{}", field.index()), None), - ProjectionElem::Index(ref index) => + ProjectionElem::Index(index) => ("", format!(""), Some(index)), ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => ("", format!("[{} of {}]", offset, min_length), None), @@ -1021,23 +1016,11 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> self.append_lvalue_to_string(&proj.base, buf); if let Some(index) = index_operand { buf.push_str("["); - self.append_operand_to_string(index, buf); + self.append_lvalue_to_string(&Lvalue::Local(index), buf); buf.push_str("]"); } else { buf.push_str(&suffix); } - - } - } - } - - fn append_operand_to_string(&self, operand: &Operand, buf: &mut String) { - match *operand { - Operand::Consume(ref lvalue) => { - self.append_lvalue_to_string(lvalue, buf); - } - Operand::Constant(ref constant) => { - buf.push_str(&format!("{:?}", constant)); } } } diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 01b76af1576f8..9cbaff2c113b6 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -61,7 +61,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // region_scope=None so lvalue indexes live forever. They are scalars so they // do not need storage annotations, and they are often copied between // places. - let idx = unpack!(block = this.as_operand(block, None, index)); + let idx = unpack!(block = this.as_temp(block, None, index)); // bounds check: let (len, lt) = (this.temp(usize_ty.clone(), expr_span), @@ -70,12 +70,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { &len, Rvalue::Len(slice.clone())); this.cfg.push_assign(block, source_info, // lt = idx < len <, Rvalue::BinaryOp(BinOp::Lt, - idx.clone(), + Operand::Consume(Lvalue::Local(idx)), Operand::Consume(len.clone()))); let msg = AssertMessage::BoundsCheck { len: Operand::Consume(len), - index: idx.clone() + index: Operand::Consume(Lvalue::Local(idx)) }; let success = this.assert(block, Operand::Consume(lt), true, msg, expr_span); @@ -127,7 +127,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Some(Category::Lvalue) => false, _ => true, }); - this.as_temp(block, expr.temp_lifetime, expr) + let temp = unpack!(block = this.as_temp(block, expr.temp_lifetime, expr)); + block.and(Lvalue::Local(temp)) } } } diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index ea1b53add5ee1..0a72ce8d05e14 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Category::Rvalue(..) => { let operand = unpack!(block = this.as_temp(block, scope, expr)); - block.and(Operand::Consume(operand)) + block.and(Operand::Consume(Lvalue::Local(operand))) } } } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index cac1535b9fe35..c83283ee38e1f 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -96,23 +96,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } ExprKind::Box { value } => { let value = this.hir.mirror(value); - let result = this.temp(expr.ty, expr_span); + let result = this.local_decls.push(LocalDecl::new_temp(expr.ty, expr_span)); this.cfg.push(block, Statement { source_info, - kind: StatementKind::StorageLive(result.clone()) + kind: StatementKind::StorageLive(result) }); if let Some(scope) = scope { // schedule a shallow free of that memory, lest we unwind: - this.schedule_drop(expr_span, scope, &result, value.ty); + this.schedule_drop(expr_span, scope, &Lvalue::Local(result), value.ty); } // malloc some memory of suitable type (thus far, uninitialized): let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); - this.cfg.push_assign(block, source_info, &result, box_); + this.cfg.push_assign(block, source_info, &Lvalue::Local(result), box_); // initialize the box contents: - unpack!(block = this.into(&result.clone().deref(), block, value)); - block.and(Rvalue::Use(Operand::Consume(result))) + unpack!(block = this.into(&Lvalue::Local(result).deref(), block, value)); + block.and(Rvalue::Use(Operand::Consume(Lvalue::Local(result)))) } ExprKind::Cast { source } => { let source = this.hir.mirror(source); diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index ed259867a48fc..7826769600bfa 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -23,7 +23,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block: BasicBlock, temp_lifetime: Option, expr: M) - -> BlockAnd> + -> BlockAnd where M: Mirror<'tcx, Output = Expr<'tcx>> { let expr = self.hir.mirror(expr); @@ -34,7 +34,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { mut block: BasicBlock, temp_lifetime: Option, expr: Expr<'tcx>) - -> BlockAnd> { + -> BlockAnd { debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})", block, temp_lifetime, expr); let this = self; @@ -47,13 +47,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }); } - let expr_ty = expr.ty.clone(); - let temp = this.temp(expr_ty.clone(), expr_span); + let expr_ty = expr.ty; + let temp = this.local_decls.push(LocalDecl::new_temp(expr_ty, expr_span)); if !expr_ty.is_never() { this.cfg.push(block, Statement { source_info, - kind: StatementKind::StorageLive(temp.clone()) + kind: StatementKind::StorageLive(temp) }); } @@ -68,10 +68,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Category::Lvalue => { let lvalue = unpack!(block = this.as_lvalue(block, expr)); let rvalue = Rvalue::Use(Operand::Consume(lvalue)); - this.cfg.push_assign(block, source_info, &temp, rvalue); + this.cfg.push_assign(block, source_info, &Lvalue::Local(temp), rvalue); } _ => { - unpack!(block = this.into(&temp, block, expr)); + unpack!(block = this.into(&Lvalue::Local(temp), block, expr)); } } @@ -79,7 +79,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // anything because no values with a destructor can be created in // a constant at this time, even if the type may need dropping. if let Some(temp_lifetime) = temp_lifetime { - this.schedule_drop(expr_span, temp_lifetime, &temp, expr_ty); + this.schedule_drop(expr_span, temp_lifetime, &Lvalue::Local(temp), expr_ty); } block.and(temp) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 6d7c213266567..80a126dc42569 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -229,7 +229,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let topmost_scope = this.topmost_scope(); let ptr = unpack!(block = this.as_temp(block, Some(topmost_scope), ptr)); - this.into(&ptr.deref(), block, val) + this.into(&Lvalue::Local(ptr).deref(), block, val) } else { let args: Vec<_> = args.into_iter() diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index a2b376336b806..ec2e487b4e74c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -194,7 +194,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); self.cfg.push(block, Statement { source_info, - kind: StatementKind::StorageLive(Lvalue::Local(local_id)) + kind: StatementKind::StorageLive(local_id) }); Lvalue::Local(local_id) } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index f527c4f03880b..ed598c876f3e9 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -822,7 +822,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, Lvalue::Local(index) if index.index() > arg_count => { cfg.push(block, Statement { source_info, - kind: StatementKind::StorageDead(drop_data.location.clone()) + kind: StatementKind::StorageDead(index) }); } _ => continue diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs index 173396f22457a..00825c7a880e9 100644 --- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs +++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs @@ -21,8 +21,7 @@ //! `a[x]` would still overlap them both. But that is not this //! representation does today.) -use rustc::mir::LvalueElem; -use rustc::mir::{Operand, ProjectionElem}; +use rustc::mir::{Local, LvalueElem, Operand, ProjectionElem}; use rustc::ty::Ty; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -40,6 +39,10 @@ impl<'tcx> Lift for Operand<'tcx> { type Abstract = AbstractOperand; fn lift(&self) -> Self::Abstract { AbstractOperand } } +impl Lift for Local { + type Abstract = AbstractOperand; + fn lift(&self) -> Self::Abstract { AbstractOperand } +} impl<'tcx> Lift for Ty<'tcx> { type Abstract = AbstractType; fn lift(&self) -> Self::Abstract { AbstractType } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 1e0858d686451..d3c886dab4e86 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -479,9 +479,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { fn array_shim(&mut self, ty: ty::Ty<'tcx>, len: usize) { let tcx = self.tcx; + let span = self.span; let rcvr = Lvalue::Local(Local::new(1+0)).deref(); - let beg = self.make_lvalue(Mutability::Mut, tcx.types.usize); + let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span)); let end = self.make_lvalue(Mutability::Not, tcx.types.usize); let ret = self.make_lvalue(Mutability::Mut, tcx.mk_array(ty, len)); @@ -492,7 +493,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { let inits = vec![ self.make_statement( StatementKind::Assign( - beg.clone(), + Lvalue::Local(beg), Rvalue::Use(Operand::Constant(self.make_usize(0))) ) ), @@ -510,19 +511,19 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { // BB #3; // } // BB #4; - self.loop_header(beg.clone(), end, BasicBlock::new(2), BasicBlock::new(4), false); + self.loop_header(Lvalue::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false); // BB #2 // `let cloned = Clone::clone(rcvr[beg])`; // Goto #3 if ok, #5 if unwinding happens. - let rcvr_field = rcvr.clone().index(Operand::Consume(beg.clone())); + let rcvr_field = rcvr.clone().index(beg); let cloned = self.make_clone_call(ty, rcvr_field, BasicBlock::new(3), BasicBlock::new(5)); // BB #3 // `ret[beg] = cloned;` // `beg = beg + 1;` // `goto #1`; - let ret_field = ret.clone().index(Operand::Consume(beg.clone())); + let ret_field = ret.clone().index(beg); let statements = vec![ self.make_statement( StatementKind::Assign( @@ -532,10 +533,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { ), self.make_statement( StatementKind::Assign( - beg.clone(), + Lvalue::Local(beg), Rvalue::BinaryOp( BinOp::Add, - Operand::Consume(beg.clone()), + Operand::Consume(Lvalue::Local(beg)), Operand::Constant(self.make_usize(1)) ) ) @@ -558,10 +559,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { // `let mut beg = 0;` // goto #6; let end = beg; - let beg = self.make_lvalue(Mutability::Mut, tcx.types.usize); + let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span)); let init = self.make_statement( StatementKind::Assign( - beg.clone(), + Lvalue::Local(beg), Rvalue::Use(Operand::Constant(self.make_usize(0))) ) ); @@ -572,12 +573,13 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { // BB #8; // } // BB #9; - self.loop_header(beg.clone(), end, BasicBlock::new(7), BasicBlock::new(9), true); + self.loop_header(Lvalue::Local(beg), Lvalue::Local(end), + BasicBlock::new(7), BasicBlock::new(9), true); // BB #7 (cleanup) // `drop(ret[beg])`; self.block(vec![], TerminatorKind::Drop { - location: ret.index(Operand::Consume(beg.clone())), + location: ret.index(beg), target: BasicBlock::new(8), unwind: None, }, true); @@ -587,10 +589,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { // `goto #6;` let statement = self.make_statement( StatementKind::Assign( - beg.clone(), + Lvalue::Local(beg), Rvalue::BinaryOp( BinOp::Add, - Operand::Consume(beg.clone()), + Operand::Consume(Lvalue::Local(beg)), Operand::Constant(self.make_usize(1)) ) ) diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 186c465f60105..ac8ebd306d321 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -236,8 +236,7 @@ impl<'tcx> Action<'tcx> { } // Replace all uses of the destination local with the source local. - let src_lvalue = Lvalue::Local(src_local); - def_use_analysis.replace_all_defs_and_uses_with(dest_local, mir, src_lvalue); + def_use_analysis.replace_all_defs_and_uses_with(dest_local, mir, src_local); // Finally, zap the now-useless assignment instruction. debug!(" Deleting assignment"); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 9bc572c66b6f8..d1e0465f5551c 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -88,7 +88,9 @@ struct RenameLocalVisitor { impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor { fn visit_local(&mut self, - local: &mut Local) { + local: &mut Local, + _: LvalueContext<'tcx>, + _: Location) { if *local == self.from { *local = self.to; } @@ -98,6 +100,13 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor { struct DerefArgVisitor; impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor { + fn visit_local(&mut self, + local: &mut Local, + _: LvalueContext<'tcx>, + _: Location) { + assert_ne!(*local, self_arg()); + } + fn visit_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>, context: LvalueContext<'tcx>, @@ -177,6 +186,13 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { } impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> { + fn visit_local(&mut self, + local: &mut Local, + _: LvalueContext<'tcx>, + _: Location) { + assert_eq!(self.remap.get(local), None); + } + fn visit_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>, context: LvalueContext<'tcx>, @@ -197,12 +213,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> { // Remove StorageLive and StorageDead statements for remapped locals data.retain_statements(|s| { match s.kind { - StatementKind::StorageLive(ref l) | StatementKind::StorageDead(ref l) => { - if let Lvalue::Local(l) = *l { - !self.remap.contains_key(&l) - } else { - true - } + StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => { + !self.remap.contains_key(&l) } _ => true } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 124a1ef946e2b..3f8070fb3aa31 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -589,16 +589,6 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { new } - fn update_local(&self, local: Local) -> Option { - let idx = local.index(); - if idx < (self.args.len() + 1) { - return None; - } - let idx = idx - (self.args.len() + 1); - let local = Local::new(idx); - self.local_map.get(local).cloned() - } - fn arg_index(&self, arg: Local) -> Option { let idx = arg.index(); if idx > 0 && idx <= self.args.len() { @@ -610,32 +600,35 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { } impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { + fn visit_local(&mut self, + local: &mut Local, + _ctxt: LvalueContext<'tcx>, + _location: Location) { + if *local == RETURN_POINTER { + match self.destination { + Lvalue::Local(l) => *local = l, + ref lval => bug!("Return lvalue is {:?}, not local", lval) + } + } + let idx = local.index() - 1; + if idx < self.args.len() { + match self.args[idx] { + Operand::Consume(Lvalue::Local(l)) => *local = l, + ref op => bug!("Arg operand `{:?}` is {:?}, not local", idx, op) + } + } + *local = self.local_map[Local::new(idx - self.args.len())]; + } + fn visit_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>, _ctxt: LvalueContext<'tcx>, _location: Location) { - if let Lvalue::Local(ref mut local) = *lvalue { - if let Some(l) = self.update_local(*local) { - // Temp or Var; update the local reference - *local = l; - return; - } - } - if let Lvalue::Local(local) = *lvalue { - if local == RETURN_POINTER { - // Return pointer; update the lvalue itself - *lvalue = self.destination.clone(); - } else if local.index() < (self.args.len() + 1) { - // Argument, once again update the the lvalue itself - let idx = local.index() - 1; - if let Operand::Consume(ref lval) = self.args[idx] { - *lvalue = lval.clone(); - } else { - bug!("Arg operand `{:?}` is not an Lvalue use.", idx) - } - } + if let Lvalue::Local(RETURN_POINTER) = *lvalue { + // Return pointer; update the lvalue itself + *lvalue = self.destination.clone(); } else { - self.super_lvalue(lvalue, _ctxt, _location) + self.super_lvalue(lvalue, _ctxt, _location); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 3e136fb9e9c49..ca6eda5c2d716 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -83,52 +83,49 @@ struct TempCollector<'tcx> { } impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { - fn visit_lvalue(&mut self, - lvalue: &Lvalue<'tcx>, - context: LvalueContext<'tcx>, - location: Location) { - self.super_lvalue(lvalue, context, location); - if let Lvalue::Local(index) = *lvalue { - // We're only interested in temporaries - if self.mir.local_kind(index) != LocalKind::Temp { - return; - } + fn visit_local(&mut self, + &index: &Local, + context: LvalueContext<'tcx>, + location: Location) { + // We're only interested in temporaries + if self.mir.local_kind(index) != LocalKind::Temp { + return; + } - // Ignore drops, if the temp gets promoted, - // then it's constant and thus drop is noop. - // Storage live ranges are also irrelevant. - if context.is_drop() || context.is_storage_marker() { - return; - } + // Ignore drops, if the temp gets promoted, + // then it's constant and thus drop is noop. + // Storage live ranges are also irrelevant. + if context.is_drop() || context.is_storage_marker() { + return; + } - let temp = &mut self.temps[index]; - if *temp == TempState::Undefined { - match context { - LvalueContext::Store | - LvalueContext::Call => { - *temp = TempState::Defined { - location, - uses: 0 - }; - return; - } - _ => { /* mark as unpromotable below */ } - } - } else if let TempState::Defined { ref mut uses, .. } = *temp { - // We always allow borrows, even mutable ones, as we need - // to promote mutable borrows of some ZSTs e.g. `&mut []`. - let allowed_use = match context { - LvalueContext::Borrow {..} => true, - _ => context.is_nonmutating_use() - }; - if allowed_use { - *uses += 1; + let temp = &mut self.temps[index]; + if *temp == TempState::Undefined { + match context { + LvalueContext::Store | + LvalueContext::Call => { + *temp = TempState::Defined { + location, + uses: 0 + }; return; } - /* mark as unpromotable below */ + _ => { /* mark as unpromotable below */ } } - *temp = TempState::Unpromotable; + } else if let TempState::Defined { ref mut uses, .. } = *temp { + // We always allow borrows, even mutable ones, as we need + // to promote mutable borrows of some ZSTs e.g. `&mut []`. + let allowed_use = match context { + LvalueContext::Borrow {..} => true, + _ => context.is_nonmutating_use() + }; + if allowed_use { + *uses += 1; + return; + } + /* mark as unpromotable below */ } + *temp = TempState::Unpromotable; } fn visit_source_info(&mut self, source_info: &SourceInfo) { @@ -326,16 +323,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { /// Replaces all temporaries with their promoted counterparts. impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { - fn visit_lvalue(&mut self, - lvalue: &mut Lvalue<'tcx>, - context: LvalueContext<'tcx>, - location: Location) { - if let Lvalue::Local(ref mut temp) = *lvalue { - if self.source.local_kind(*temp) == LocalKind::Temp { - *temp = self.promote_temp(*temp); - } + fn visit_local(&mut self, + local: &mut Local, + _: LvalueContext<'tcx>, + _: Location) { + if self.source.local_kind(*local) == LocalKind::Temp { + *local = self.promote_temp(*local); } - self.super_lvalue(lvalue, context, location); } } @@ -412,8 +406,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, block.statements.retain(|statement| { match statement.kind { StatementKind::Assign(Lvalue::Local(index), _) | - StatementKind::StorageLive(Lvalue::Local(index)) | - StatementKind::StorageDead(Lvalue::Local(index)) => { + StatementKind::StorageLive(index) | + StatementKind::StorageDead(index) => { !promoted(index) } _ => true diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 9e64b0f9c77be..415421757c5c5 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -499,33 +499,40 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { /// For functions (constant or not), it also records /// candidates for promotion in promotion_candidates. impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { + fn visit_local(&mut self, + &local: &Local, + _: LvalueContext<'tcx>, + _: Location) { + match self.mir.local_kind(local) { + LocalKind::ReturnPointer => { + self.not_const(); + } + LocalKind::Arg => { + self.add(Qualif::FN_ARGUMENT); + } + LocalKind::Var => { + self.add(Qualif::NOT_CONST); + } + LocalKind::Temp => { + if !self.temp_promotion_state[local].is_promotable() { + self.add(Qualif::NOT_PROMOTABLE); + } + + if let Some(qualif) = self.temp_qualif[local] { + self.add(qualif); + } else { + self.not_const(); + } + } + } + } + fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext<'tcx>, location: Location) { match *lvalue { - Lvalue::Local(local) => match self.mir.local_kind(local) { - LocalKind::ReturnPointer => { - self.not_const(); - } - LocalKind::Arg => { - self.add(Qualif::FN_ARGUMENT); - } - LocalKind::Var => { - self.add(Qualif::NOT_CONST); - } - LocalKind::Temp => { - if !self.temp_promotion_state[local].is_promotable() { - self.add(Qualif::NOT_PROMOTABLE); - } - - if let Some(qualif) = self.temp_qualif[local] { - self.add(qualif); - } else { - self.not_const(); - } - } - }, + Lvalue::Local(ref local) => self.visit_local(local, context, location), Lvalue::Static(ref global) => { self.add(Qualif::STATIC); @@ -1101,7 +1108,7 @@ impl MirPass for QualifyAndPromoteConstants { for block in mir.basic_blocks_mut() { block.statements.retain(|statement| { match statement.kind { - StatementKind::StorageDead(Lvalue::Local(index)) => { + StatementKind::StorageDead(index) => { !promoted_temps.contains(&index) } _ => true diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 070250cda4d5d..89828cf375aa7 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -352,15 +352,11 @@ struct DeclMarker { } impl<'tcx> Visitor<'tcx> for DeclMarker { - fn visit_lvalue(&mut self, lval: &Lvalue<'tcx>, ctx: LvalueContext<'tcx>, loc: Location) { - if ctx == LvalueContext::StorageLive || ctx == LvalueContext::StorageDead { - // ignore these altogether, they get removed along with their otherwise unused decls. - return; + fn visit_local(&mut self, local: &Local, ctx: LvalueContext<'tcx>, _: Location) { + // ignore these altogether, they get removed along with their otherwise unused decls. + if ctx != LvalueContext::StorageLive && ctx != LvalueContext::StorageDead { + self.locals.insert(local.index()); } - if let Lvalue::Local(ref v) = *lval { - self.locals.insert(v.index()); - } - self.super_lvalue(lval, ctx, loc); } } @@ -373,22 +369,15 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater { // Remove unnecessary StorageLive and StorageDead annotations. data.statements.retain(|stmt| { match stmt.kind { - StatementKind::StorageLive(ref lval) | StatementKind::StorageDead(ref lval) => { - match *lval { - Lvalue::Local(l) => self.map[l.index()] != !0, - _ => true - } + StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => { + self.map[l.index()] != !0 } _ => true } }); self.super_basic_block_data(block, data); } - fn visit_lvalue(&mut self, lval: &mut Lvalue<'tcx>, ctx: LvalueContext<'tcx>, loc: Location) { - match *lval { - Lvalue::Local(ref mut l) => *l = Local::new(self.map[l.index()]), - _ => (), - }; - self.super_lvalue(lval, ctx, loc); + fn visit_local(&mut self, l: &mut Local, _: LvalueContext<'tcx>, _: Location) { + *l = Local::new(self.map[l.index()]); } } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 59cf5903aa9a0..d4da14ea96e72 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -165,7 +165,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { base: LvalueTy<'tcx>, pi: &LvalueElem<'tcx>, lvalue: &Lvalue<'tcx>, - location: Location) + _: Location) -> LvalueTy<'tcx> { debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, lvalue); let tcx = self.tcx(); @@ -181,9 +181,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }) } } - ProjectionElem::Index(ref i) => { - self.visit_operand(i, location); - let index_ty = i.ty(self.mir, tcx); + ProjectionElem::Index(i) => { + let index_ty = Lvalue::Local(i).ty(self.mir, tcx).to_ty(tcx); if index_ty != tcx.types.usize { LvalueTy::Ty { ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i) @@ -421,15 +420,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { variant_index); }; } - StatementKind::StorageLive(ref lv) | - StatementKind::StorageDead(ref lv) => { - match *lv { - Lvalue::Local(_) => {} - _ => { - span_mirbug!(self, stmt, "bad lvalue: expected local"); - } - } - } + StatementKind::StorageLive(_) | + StatementKind::StorageDead(_) | StatementKind::InlineAsm { .. } | StatementKind::EndRegion(_) | StatementKind::Validate(..) | diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 8263e149d84e7..bd9fb4bc3cc5f 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -10,7 +10,7 @@ //! Def-use analysis. -use rustc::mir::{Local, Location, Lvalue, Mir}; +use rustc::mir::{Local, Location, Mir}; use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor}; use rustc_data_structures::indexed_vec::IndexVec; use std::marker::PhantomData; @@ -51,7 +51,7 @@ impl<'tcx> DefUseAnalysis<'tcx> { } fn mutate_defs_and_uses(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F) - where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, + where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) { for lvalue_use in &self.info[local].defs_and_uses { @@ -65,8 +65,8 @@ impl<'tcx> DefUseAnalysis<'tcx> { pub fn replace_all_defs_and_uses_with(&self, local: Local, mir: &mut Mir<'tcx>, - new_lvalue: Lvalue<'tcx>) { - self.mutate_defs_and_uses(local, mir, |lvalue, _, _| *lvalue = new_lvalue.clone()) + new_local: Local) { + self.mutate_defs_and_uses(local, mir, |local, _, _| *local = new_local) } } @@ -74,30 +74,15 @@ struct DefUseFinder<'tcx> { info: IndexVec>, } -impl<'tcx> DefUseFinder<'tcx> { - fn lvalue_mut_info(&mut self, lvalue: &Lvalue<'tcx>) -> Option<&mut Info<'tcx>> { - let info = &mut self.info; - - if let Lvalue::Local(local) = *lvalue { - Some(&mut info[local]) - } else { - None - } - } -} - impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> { - fn visit_lvalue(&mut self, - lvalue: &Lvalue<'tcx>, - context: LvalueContext<'tcx>, - location: Location) { - if let Some(ref mut info) = self.lvalue_mut_info(lvalue) { - info.defs_and_uses.push(Use { - context, - location, - }) - } - self.super_lvalue(lvalue, context, location) + fn visit_local(&mut self, + &local: &Local, + context: LvalueContext<'tcx>, + location: Location) { + self.info[local].defs_and_uses.push(Use { + context, + location, + }); } } @@ -134,7 +119,7 @@ struct MutateUseVisitor<'tcx, F> { impl<'tcx, F> MutateUseVisitor<'tcx, F> { fn new(query: Local, callback: F, _: &Mir<'tcx>) -> MutateUseVisitor<'tcx, F> - where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) { + where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) { MutateUseVisitor { query, callback, @@ -144,16 +129,13 @@ impl<'tcx, F> MutateUseVisitor<'tcx, F> { } impl<'tcx, F> MutVisitor<'tcx> for MutateUseVisitor<'tcx, F> - where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) { - fn visit_lvalue(&mut self, - lvalue: &mut Lvalue<'tcx>, + where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) { + fn visit_local(&mut self, + local: &mut Local, context: LvalueContext<'tcx>, location: Location) { - if let Lvalue::Local(local) = *lvalue { - if local == self.query { - (self.callback)(lvalue, context, location) - } + if *local == self.query { + (self.callback)(local, context, location) } - self.super_lvalue(lvalue, context, location) } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 41618960337be..f3b121f2eed57 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -565,7 +565,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> /// drop(ptr) fn drop_loop(&mut self, succ: BasicBlock, - cur: &Lvalue<'tcx>, + cur: Local, length_or_end: &Lvalue<'tcx>, ety: Ty<'tcx>, unwind: Unwind, @@ -584,20 +584,20 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let one = self.constant_usize(1); let (ptr_next, cur_next) = if ptr_based { - (Rvalue::Use(use_(cur)), - Rvalue::BinaryOp(BinOp::Offset, use_(cur), one)) + (Rvalue::Use(use_(&Lvalue::Local(cur))), + Rvalue::BinaryOp(BinOp::Offset, use_(&Lvalue::Local(cur)), one)) } else { (Rvalue::Ref( tcx.types.re_erased, BorrowKind::Mut, - self.lvalue.clone().index(use_(cur))), - Rvalue::BinaryOp(BinOp::Add, use_(cur), one)) + self.lvalue.clone().index(cur)), + Rvalue::BinaryOp(BinOp::Add, use_(&Lvalue::Local(cur)), one)) }; let drop_block = BasicBlockData { statements: vec![ self.assign(ptr, ptr_next), - self.assign(cur, cur_next) + self.assign(&Lvalue::Local(cur), cur_next) ], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { @@ -611,7 +611,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let loop_block = BasicBlockData { statements: vec![ self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq, - use_(cur), + use_(&Lvalue::Local(cur)), use_(length_or_end))) ], is_cleanup: unwind.is_cleanup(), @@ -678,7 +678,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> tcx.types.usize }; - let cur = Lvalue::Local(self.new_temp(iter_ty)); + let cur = self.new_temp(iter_ty); let length = Lvalue::Local(self.new_temp(tcx.types.usize)); let length_or_end = if ptr_based { Lvalue::Local(self.new_temp(iter_ty)) @@ -688,7 +688,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let unwind = self.unwind.map(|unwind| { self.drop_loop(unwind, - &cur, + cur, &length_or_end, ety, Unwind::InCleanup, @@ -698,12 +698,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let succ = self.succ; // FIXME(#6393) let loop_block = self.drop_loop( succ, - &cur, + cur, &length_or_end, ety, unwind, ptr_based); + let cur = Lvalue::Local(cur); let zero = self.constant_usize(0); let mut drop_block_stmts = vec![]; drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.lvalue.clone()))); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index fd15c90dc9013..e6d3a82ff9b53 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -60,49 +60,45 @@ struct BlockInfoVisitor { } impl<'tcx> Visitor<'tcx> for BlockInfoVisitor { - fn visit_lvalue(&mut self, - lvalue: &Lvalue<'tcx>, - context: LvalueContext<'tcx>, - location: Location) { - if let Lvalue::Local(local) = *lvalue { - match context { - LvalueContext::Store | - - // We let Call defined the result in both the success and unwind cases. - // This may not be right. - LvalueContext::Call | - - // Storage live and storage dead aren't proper defines, but we can ignore - // values that come before them. - LvalueContext::StorageLive | - LvalueContext::StorageDead => { - self.defs.add(&local); - } - LvalueContext::Projection(..) | - - // Borrows only consider their local used at the point of the borrow. - // This won't affect the results since we use this analysis for generators - // and we only care about the result at suspension points. Borrows cannot - // cross suspension points so this behavior is unproblematic. - LvalueContext::Borrow { .. } | - - LvalueContext::Inspect | - LvalueContext::Consume | - LvalueContext::Validate | - - // We consider drops to always be uses of locals. - // Drop eloboration should be run before this analysis otherwise - // the results might be too pessimistic. - LvalueContext::Drop => { - // Ignore uses which are already defined in this block - if !self.pre_defs.contains(&local) { - self.uses.add(&local); - } + fn visit_local(&mut self, + &local: &Local, + context: LvalueContext<'tcx>, + _: Location) { + match context { + LvalueContext::Store | + + // We let Call defined the result in both the success and unwind cases. + // This may not be right. + LvalueContext::Call | + + // Storage live and storage dead aren't proper defines, but we can ignore + // values that come before them. + LvalueContext::StorageLive | + LvalueContext::StorageDead => { + self.defs.add(&local); + } + LvalueContext::Projection(..) | + + // Borrows only consider their local used at the point of the borrow. + // This won't affect the results since we use this analysis for generators + // and we only care about the result at suspension points. Borrows cannot + // cross suspension points so this behavior is unproblematic. + LvalueContext::Borrow { .. } | + + LvalueContext::Inspect | + LvalueContext::Consume | + LvalueContext::Validate | + + // We consider drops to always be uses of locals. + // Drop eloboration should be run before this analysis otherwise + // the results might be too pessimistic. + LvalueContext::Drop => { + // Ignore uses which are already defined in this block + if !self.pre_defs.contains(&local) { + self.uses.add(&local); } } } - - self.super_lvalue(lvalue, context, location) } } diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index a17ddabb1a7cd..95b76d32bf848 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -134,60 +134,61 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { location: Location) { debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context); - // Allow uses of projections of immediate pair fields. if let mir::Lvalue::Projection(ref proj) = *lvalue { - if let mir::Lvalue::Local(_) = proj.base { - let ty = proj.base.ty(self.cx.mir, self.cx.ccx.tcx()); - - let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx())); - if common::type_is_imm_pair(self.cx.ccx, ty) { + // Allow uses of projections of immediate pair fields. + if let LvalueContext::Consume = context { + if let mir::Lvalue::Local(_) = proj.base { if let mir::ProjectionElem::Field(..) = proj.elem { - if let LvalueContext::Consume = context { + let ty = proj.base.ty(self.cx.mir, self.cx.ccx.tcx()); + + let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx())); + if common::type_is_imm_pair(self.cx.ccx, ty) { return; } } } } - } - if let mir::Lvalue::Local(index) = *lvalue { - match context { - LvalueContext::Call => { - self.mark_assigned(index); - } + // A deref projection only reads the pointer, never needs the lvalue. + if let mir::ProjectionElem::Deref = proj.elem { + return self.visit_lvalue(&proj.base, LvalueContext::Consume, location); + } + } - LvalueContext::StorageLive | - LvalueContext::StorageDead | - LvalueContext::Validate | - LvalueContext::Inspect | - LvalueContext::Consume => {} + self.super_lvalue(lvalue, context, location); + } - LvalueContext::Store | - LvalueContext::Borrow { .. } | - LvalueContext::Projection(..) => { - self.mark_as_lvalue(index); - } + fn visit_local(&mut self, + &index: &mir::Local, + context: LvalueContext<'tcx>, + _: Location) { + match context { + LvalueContext::Call => { + self.mark_assigned(index); + } - LvalueContext::Drop => { - let ty = lvalue.ty(self.cx.mir, self.cx.ccx.tcx()); - let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx())); + LvalueContext::StorageLive | + LvalueContext::StorageDead | + LvalueContext::Validate | + LvalueContext::Inspect | + LvalueContext::Consume => {} - // Only need the lvalue if we're actually dropping it. - if self.cx.ccx.shared().type_needs_drop(ty) { - self.mark_as_lvalue(index); - } - } + LvalueContext::Store | + LvalueContext::Borrow { .. } | + LvalueContext::Projection(..) => { + self.mark_as_lvalue(index); } - } - // A deref projection only reads the pointer, never needs the lvalue. - if let mir::Lvalue::Projection(ref proj) = *lvalue { - if let mir::ProjectionElem::Deref = proj.elem { - return self.visit_lvalue(&proj.base, LvalueContext::Consume, location); + LvalueContext::Drop => { + let ty = mir::Lvalue::Local(index).ty(self.cx.mir, self.cx.ccx.tcx()); + let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx())); + + // Only need the lvalue if we're actually dropping it. + if self.cx.ccx.shared().type_needs_drop(ty) { + self.mark_as_lvalue(index); + } } } - - self.super_lvalue(lvalue, context, location); } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 65b9fec7eff49..9987c9c33102d 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -471,7 +471,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { }; (Base::Value(llprojected), llextra) } - mir::ProjectionElem::Index(ref index) => { + mir::ProjectionElem::Index(index) => { + let index = &mir::Operand::Consume(mir::Lvalue::Local(index)); let llindex = self.const_operand(index, span)?.llval; let iv = if let Some(iv) = common::const_to_opt_u128(llindex, false) { diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index 89c76ccdd27c2..8155303b0d3fc 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -333,7 +333,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { }; (tr_base.trans_field_ptr(bcx, field.index()), llextra) } - mir::ProjectionElem::Index(ref index) => { + mir::ProjectionElem::Index(index) => { + let index = &mir::Operand::Consume(mir::Lvalue::Local(index)); let index = self.trans_operand(bcx, index); let llindex = self.prepare_index(bcx, index.immediate()); ((tr_base.project_index(bcx, llindex), align), ptr::null_mut()) diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 52dfc8dc4de5c..bbf661ae9a735 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -67,11 +67,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { variant_index as u64); bcx } - mir::StatementKind::StorageLive(ref lvalue) => { - self.trans_storage_liveness(bcx, lvalue, base::Lifetime::Start) + mir::StatementKind::StorageLive(local) => { + self.trans_storage_liveness(bcx, local, base::Lifetime::Start) } - mir::StatementKind::StorageDead(ref lvalue) => { - self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End) + mir::StatementKind::StorageDead(local) => { + self.trans_storage_liveness(bcx, local, base::Lifetime::End) } mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { let outputs = outputs.iter().map(|output| { @@ -94,13 +94,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { fn trans_storage_liveness(&self, bcx: Builder<'a, 'tcx>, - lvalue: &mir::Lvalue<'tcx>, + index: mir::Local, intrinsic: base::Lifetime) -> Builder<'a, 'tcx> { - if let mir::Lvalue::Local(index) = *lvalue { - if let LocalRef::Lvalue(tr_lval) = self.locals[index] { - intrinsic.call(&bcx, tr_lval.llval); - } + if let LocalRef::Lvalue(tr_lval) = self.locals[index] { + intrinsic.call(&bcx, tr_lval.llval); } bcx }