diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index f511d820fac58..5279d05260896 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -1239,3 +1239,14 @@ impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> { type Item = BasicBlock; type Iter = IntoIter; } + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)] +pub struct Location { + /// the location is within this block + pub block: BasicBlock, + + /// the location is the start of the this statement; or, if `statement_index` + /// == num-statements, then the start of the terminator. + pub statement_index: usize, +} + diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ead8de86dbae4..0a0872b5edafe 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -103,60 +103,70 @@ macro_rules! make_mir_visitor { fn visit_statement(&mut self, block: BasicBlock, - statement: & $($mutability)* Statement<'tcx>) { - self.super_statement(block, statement); + statement: & $($mutability)* Statement<'tcx>, + location: Location) { + self.super_statement(block, statement, location); } fn visit_assign(&mut self, block: BasicBlock, lvalue: & $($mutability)* Lvalue<'tcx>, - rvalue: & $($mutability)* Rvalue<'tcx>) { - self.super_assign(block, lvalue, rvalue); + rvalue: & $($mutability)* Rvalue<'tcx>, + location: Location) { + self.super_assign(block, lvalue, rvalue, location); } fn visit_terminator(&mut self, block: BasicBlock, - terminator: & $($mutability)* Terminator<'tcx>) { - self.super_terminator(block, terminator); + terminator: & $($mutability)* Terminator<'tcx>, + location: Location) { + self.super_terminator(block, terminator, location); } fn visit_terminator_kind(&mut self, block: BasicBlock, - kind: & $($mutability)* TerminatorKind<'tcx>) { - self.super_terminator_kind(block, kind); + kind: & $($mutability)* TerminatorKind<'tcx>, + location: Location) { + self.super_terminator_kind(block, kind, location); } fn visit_assert_message(&mut self, - msg: & $($mutability)* AssertMessage<'tcx>) { - self.super_assert_message(msg); + msg: & $($mutability)* AssertMessage<'tcx>, + location: Location) { + self.super_assert_message(msg, location); } fn visit_rvalue(&mut self, - rvalue: & $($mutability)* Rvalue<'tcx>) { - self.super_rvalue(rvalue); + rvalue: & $($mutability)* Rvalue<'tcx>, + location: Location) { + self.super_rvalue(rvalue, location); } fn visit_operand(&mut self, - operand: & $($mutability)* Operand<'tcx>) { - self.super_operand(operand); + operand: & $($mutability)* Operand<'tcx>, + location: Location) { + self.super_operand(operand, location); } fn visit_lvalue(&mut self, lvalue: & $($mutability)* Lvalue<'tcx>, - context: LvalueContext) { - self.super_lvalue(lvalue, context); + context: LvalueContext, + location: Location) { + self.super_lvalue(lvalue, context, location); } fn visit_projection(&mut self, lvalue: & $($mutability)* LvalueProjection<'tcx>, - context: LvalueContext) { - self.super_projection(lvalue, context); + context: LvalueContext, + location: Location) { + self.super_projection(lvalue, context, location); } fn visit_projection_elem(&mut self, lvalue: & $($mutability)* LvalueElem<'tcx>, - context: LvalueContext) { - self.super_projection_elem(lvalue, context); + context: LvalueContext, + location: Location) { + self.super_projection_elem(lvalue, context, location); } fn visit_branch(&mut self, @@ -166,17 +176,20 @@ macro_rules! make_mir_visitor { } fn visit_constant(&mut self, - constant: & $($mutability)* Constant<'tcx>) { - self.super_constant(constant); + constant: & $($mutability)* Constant<'tcx>, + location: Location) { + self.super_constant(constant, location); } fn visit_literal(&mut self, - literal: & $($mutability)* Literal<'tcx>) { - self.super_literal(literal); + literal: & $($mutability)* Literal<'tcx>, + location: Location) { + self.super_literal(literal, location); } fn visit_def_id(&mut self, - def_id: & $($mutability)* DefId) { + def_id: & $($mutability)* DefId, + _: Location) { self.super_def_id(def_id); } @@ -206,18 +219,21 @@ macro_rules! make_mir_visitor { } fn visit_const_val(&mut self, - const_val: & $($mutability)* ConstVal) { + const_val: & $($mutability)* ConstVal, + _: Location) { self.super_const_val(const_val); } fn visit_const_usize(&mut self, - const_usize: & $($mutability)* ConstUsize) { + const_usize: & $($mutability)* ConstUsize, + _: Location) { self.super_const_usize(const_usize); } fn visit_typed_const_val(&mut self, - val: & $($mutability)* TypedConstVal<'tcx>) { - self.super_typed_const_val(val); + val: & $($mutability)* TypedConstVal<'tcx>, + location: Location) { + self.super_typed_const_val(val, location); } fn visit_var_decl(&mut self, @@ -280,12 +296,16 @@ macro_rules! make_mir_visitor { is_cleanup: _ } = *data; + let mut index = 0; for statement in statements { - self.visit_statement(block, statement); + let location = Location { block: block, statement_index: index }; + self.visit_statement(block, statement, location); + index += 1; } if let Some(ref $($mutability)* terminator) = *terminator { - self.visit_terminator(block, terminator); + let location = Location { block: block, statement_index: index }; + self.visit_terminator(block, terminator, location); } } @@ -304,7 +324,8 @@ macro_rules! make_mir_visitor { fn super_statement(&mut self, block: BasicBlock, - statement: & $($mutability)* Statement<'tcx>) { + statement: & $($mutability)* Statement<'tcx>, + location: Location) { let Statement { ref $($mutability)* source_info, ref $($mutability)* kind, @@ -314,16 +335,16 @@ macro_rules! make_mir_visitor { match *kind { StatementKind::Assign(ref $($mutability)* lvalue, ref $($mutability)* rvalue) => { - self.visit_assign(block, lvalue, rvalue); + self.visit_assign(block, lvalue, rvalue, location); } StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => { - self.visit_lvalue(lvalue, LvalueContext::Store); + self.visit_lvalue(lvalue, LvalueContext::Store, location); } StatementKind::StorageLive(ref $($mutability)* lvalue) => { - self.visit_lvalue(lvalue, LvalueContext::StorageLive); + self.visit_lvalue(lvalue, LvalueContext::StorageLive, location); } StatementKind::StorageDead(ref $($mutability)* lvalue) => { - self.visit_lvalue(lvalue, LvalueContext::StorageDead); + self.visit_lvalue(lvalue, LvalueContext::StorageDead, location); } } } @@ -331,26 +352,29 @@ macro_rules! make_mir_visitor { fn super_assign(&mut self, _block: BasicBlock, lvalue: &$($mutability)* Lvalue<'tcx>, - rvalue: &$($mutability)* Rvalue<'tcx>) { - self.visit_lvalue(lvalue, LvalueContext::Store); - self.visit_rvalue(rvalue); + rvalue: &$($mutability)* Rvalue<'tcx>, + location: Location) { + self.visit_lvalue(lvalue, LvalueContext::Store, location); + self.visit_rvalue(rvalue, location); } fn super_terminator(&mut self, block: BasicBlock, - terminator: &$($mutability)* Terminator<'tcx>) { + terminator: &$($mutability)* Terminator<'tcx>, + location: Location) { let Terminator { ref $($mutability)* source_info, ref $($mutability)* kind, } = *terminator; self.visit_source_info(source_info); - self.visit_terminator_kind(block, kind); + self.visit_terminator_kind(block, kind, location); } fn super_terminator_kind(&mut self, block: BasicBlock, - kind: & $($mutability)* TerminatorKind<'tcx>) { + kind: & $($mutability)* TerminatorKind<'tcx>, + source_location: Location) { match *kind { TerminatorKind::Goto { target } => { self.visit_branch(block, target); @@ -358,7 +382,7 @@ macro_rules! make_mir_visitor { TerminatorKind::If { ref $($mutability)* cond, ref $($mutability)* targets } => { - self.visit_operand(cond); + self.visit_operand(cond, source_location); for &target in targets.as_slice() { self.visit_branch(block, target); } @@ -367,7 +391,7 @@ macro_rules! make_mir_visitor { TerminatorKind::Switch { ref $($mutability)* discr, adt_def: _, ref targets } => { - self.visit_lvalue(discr, LvalueContext::Inspect); + self.visit_lvalue(discr, LvalueContext::Inspect, source_location); for &target in targets { self.visit_branch(block, target); } @@ -377,10 +401,10 @@ macro_rules! make_mir_visitor { ref $($mutability)* switch_ty, ref $($mutability)* values, ref targets } => { - self.visit_lvalue(discr, LvalueContext::Inspect); + self.visit_lvalue(discr, LvalueContext::Inspect, source_location); self.visit_ty(switch_ty); for value in values { - self.visit_const_val(value); + self.visit_const_val(value, source_location); } for &target in targets { self.visit_branch(block, target); @@ -395,7 +419,7 @@ macro_rules! make_mir_visitor { TerminatorKind::Drop { ref $($mutability)* location, target, unwind } => { - self.visit_lvalue(location, LvalueContext::Drop); + self.visit_lvalue(location, LvalueContext::Drop, source_location); self.visit_branch(block, target); unwind.map(|t| self.visit_branch(block, t)); } @@ -404,8 +428,8 @@ macro_rules! make_mir_visitor { ref $($mutability)* value, target, unwind } => { - self.visit_lvalue(location, LvalueContext::Drop); - self.visit_operand(value); + self.visit_lvalue(location, LvalueContext::Drop, source_location); + self.visit_operand(value, source_location); self.visit_branch(block, target); unwind.map(|t| self.visit_branch(block, t)); } @@ -414,12 +438,12 @@ macro_rules! make_mir_visitor { ref $($mutability)* args, ref $($mutability)* destination, cleanup } => { - self.visit_operand(func); + self.visit_operand(func, source_location); for arg in args { - self.visit_operand(arg); + self.visit_operand(arg, source_location); } if let Some((ref $($mutability)* destination, target)) = *destination { - self.visit_lvalue(destination, LvalueContext::Call); + self.visit_lvalue(destination, LvalueContext::Call, source_location); self.visit_branch(block, target); } cleanup.map(|t| self.visit_branch(block, t)); @@ -430,8 +454,8 @@ macro_rules! make_mir_visitor { ref $($mutability)* msg, target, cleanup } => { - self.visit_operand(cond); - self.visit_assert_message(msg); + self.visit_operand(cond, source_location); + self.visit_assert_message(msg, source_location); self.visit_branch(block, target); cleanup.map(|t| self.visit_branch(block, t)); } @@ -439,47 +463,49 @@ macro_rules! make_mir_visitor { } fn super_assert_message(&mut self, - msg: & $($mutability)* AssertMessage<'tcx>) { + msg: & $($mutability)* AssertMessage<'tcx>, + location: Location) { match *msg { AssertMessage::BoundsCheck { ref $($mutability)* len, ref $($mutability)* index } => { - self.visit_operand(len); - self.visit_operand(index); + self.visit_operand(len, location); + self.visit_operand(index, location); } AssertMessage::Math(_) => {} } } fn super_rvalue(&mut self, - rvalue: & $($mutability)* Rvalue<'tcx>) { + rvalue: & $($mutability)* Rvalue<'tcx>, + location: Location) { match *rvalue { Rvalue::Use(ref $($mutability)* operand) => { - self.visit_operand(operand); + self.visit_operand(operand, location); } Rvalue::Repeat(ref $($mutability)* value, ref $($mutability)* typed_const_val) => { - self.visit_operand(value); - self.visit_typed_const_val(typed_const_val); + self.visit_operand(value, location); + self.visit_typed_const_val(typed_const_val, location); } Rvalue::Ref(r, bk, ref $($mutability)* path) => { self.visit_lvalue(path, LvalueContext::Borrow { region: r, kind: bk - }); + }, location); } Rvalue::Len(ref $($mutability)* path) => { - self.visit_lvalue(path, LvalueContext::Inspect); + self.visit_lvalue(path, LvalueContext::Inspect, location); } Rvalue::Cast(_cast_kind, ref $($mutability)* operand, ref $($mutability)* ty) => { - self.visit_operand(operand); + self.visit_operand(operand, location); self.visit_ty(ty); } @@ -489,12 +515,12 @@ macro_rules! make_mir_visitor { Rvalue::CheckedBinaryOp(_bin_op, ref $($mutability)* lhs, ref $($mutability)* rhs) => { - self.visit_operand(lhs); - self.visit_operand(rhs); + self.visit_operand(lhs, location); + self.visit_operand(rhs, location); } Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => { - self.visit_operand(op); + self.visit_operand(op, location); } Rvalue::Box(ref $($mutability)* ty) => { @@ -515,13 +541,13 @@ macro_rules! make_mir_visitor { } AggregateKind::Closure(ref $($mutability)* def_id, ref $($mutability)* closure_substs) => { - self.visit_def_id(def_id); + self.visit_def_id(def_id, location); self.visit_closure_substs(closure_substs); } } for operand in operands { - self.visit_operand(operand); + self.visit_operand(operand, location); } } @@ -529,30 +555,32 @@ macro_rules! make_mir_visitor { ref $($mutability)* inputs, asm: _ } => { for output in & $($mutability)* outputs[..] { - self.visit_lvalue(output, LvalueContext::Store); + self.visit_lvalue(output, LvalueContext::Store, location); } for input in & $($mutability)* inputs[..] { - self.visit_operand(input); + self.visit_operand(input, location); } } } } fn super_operand(&mut self, - operand: & $($mutability)* Operand<'tcx>) { + operand: & $($mutability)* Operand<'tcx>, + location: Location) { match *operand { Operand::Consume(ref $($mutability)* lvalue) => { - self.visit_lvalue(lvalue, LvalueContext::Consume); + self.visit_lvalue(lvalue, LvalueContext::Consume, location); } Operand::Constant(ref $($mutability)* constant) => { - self.visit_constant(constant); + self.visit_constant(constant, location); } } } fn super_lvalue(&mut self, lvalue: & $($mutability)* Lvalue<'tcx>, - context: LvalueContext) { + context: LvalueContext, + location: Location) { match *lvalue { Lvalue::Var(_) | Lvalue::Temp(_) | @@ -560,28 +588,30 @@ macro_rules! make_mir_visitor { Lvalue::ReturnPointer => { } Lvalue::Static(ref $($mutability)* def_id) => { - self.visit_def_id(def_id); + self.visit_def_id(def_id, location); } Lvalue::Projection(ref $($mutability)* proj) => { - self.visit_projection(proj, context); + self.visit_projection(proj, context, location); } } } fn super_projection(&mut self, proj: & $($mutability)* LvalueProjection<'tcx>, - context: LvalueContext) { + context: LvalueContext, + location: Location) { let Projection { ref $($mutability)* base, ref $($mutability)* elem, } = *proj; - self.visit_lvalue(base, LvalueContext::Projection); - self.visit_projection_elem(elem, context); + self.visit_lvalue(base, LvalueContext::Projection, location); + self.visit_projection_elem(elem, context, location); } fn super_projection_elem(&mut self, proj: & $($mutability)* LvalueElem<'tcx>, - _context: LvalueContext) { + _context: LvalueContext, + location: Location) { match *proj { ProjectionElem::Deref => { } @@ -591,7 +621,7 @@ macro_rules! make_mir_visitor { self.visit_ty(ty); } ProjectionElem::Index(ref $($mutability)* operand) => { - self.visit_operand(operand); + self.visit_operand(operand, location); } ProjectionElem::ConstantIndex { offset: _, min_length: _, @@ -645,7 +675,8 @@ macro_rules! make_mir_visitor { } fn super_constant(&mut self, - constant: & $($mutability)* Constant<'tcx>) { + constant: & $($mutability)* Constant<'tcx>, + location: Location) { let Constant { ref $($mutability)* span, ref $($mutability)* ty, @@ -654,11 +685,12 @@ macro_rules! make_mir_visitor { self.visit_span(span); self.visit_ty(ty); - self.visit_literal(literal); + self.visit_literal(literal, location); } fn super_typed_const_val(&mut self, - constant: & $($mutability)* TypedConstVal<'tcx>) { + constant: & $($mutability)* TypedConstVal<'tcx>, + location: Location) { let TypedConstVal { ref $($mutability)* span, ref $($mutability)* ty, @@ -667,19 +699,20 @@ macro_rules! make_mir_visitor { self.visit_span(span); self.visit_ty(ty); - self.visit_const_usize(value); + self.visit_const_usize(value, location); } fn super_literal(&mut self, - literal: & $($mutability)* Literal<'tcx>) { + literal: & $($mutability)* Literal<'tcx>, + location: Location) { match *literal { Literal::Item { ref $($mutability)* def_id, ref $($mutability)* substs } => { - self.visit_def_id(def_id); + self.visit_def_id(def_id, location); self.visit_substs(substs); } Literal::Value { ref $($mutability)* value } => { - self.visit_const_val(value); + self.visit_const_val(value, location); } Literal::Promoted { index: _ } => {} } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index 90858e4e8b8be..c46daf9c22537 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -9,10 +9,9 @@ // except according to those terms. use rustc::ty::TyCtxt; -use rustc::mir::repr::{self, Mir}; +use rustc::mir::repr::{self, Mir, Location}; use rustc_data_structures::indexed_vec::Idx; -use super::super::gather_moves::{Location}; use super::super::gather_moves::{MoveOutIndex, MovePathIndex}; use super::super::MoveDataParamEnv; use super::super::DropFlagState; @@ -252,7 +251,7 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> { { drop_flag_effects_for_location( self.tcx, self.mir, ctxt, - Location { block: bb, index: idx }, + Location { block: bb, statement_index: idx }, |path, s| Self::update_bits(sets, path, s) ) } @@ -265,7 +264,7 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> { { drop_flag_effects_for_location( self.tcx, self.mir, ctxt, - Location { block: bb, index: statements_len }, + Location { block: bb, statement_index: statements_len }, |path, s| Self::update_bits(sets, path, s) ) } @@ -314,7 +313,7 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> { { drop_flag_effects_for_location( self.tcx, self.mir, ctxt, - Location { block: bb, index: idx }, + Location { block: bb, statement_index: idx }, |path, s| Self::update_bits(sets, path, s) ) } @@ -327,7 +326,7 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> { { drop_flag_effects_for_location( self.tcx, self.mir, ctxt, - Location { block: bb, index: statements_len }, + Location { block: bb, statement_index: statements_len }, |path, s| Self::update_bits(sets, path, s) ) } @@ -375,7 +374,7 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { { drop_flag_effects_for_location( self.tcx, self.mir, ctxt, - Location { block: bb, index: idx }, + Location { block: bb, statement_index: idx }, |path, s| Self::update_bits(sets, path, s) ) } @@ -388,7 +387,7 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { { drop_flag_effects_for_location( self.tcx, self.mir, ctxt, - Location { block: bb, index: statements_len }, + Location { block: bb, statement_index: statements_len }, |path, s| Self::update_bits(sets, path, s) ) } @@ -431,7 +430,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { let path_map = &move_data.path_map; let rev_lookup = &move_data.rev_lookup; - let loc = Location { block: bb, index: idx }; + let loc = Location { block: bb, statement_index: idx }; debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", stmt, loc, &loc_map[loc]); for move_index in &loc_map[loc] { @@ -473,7 +472,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { let (mir, move_data) = (self.mir, &ctxt.move_data); let term = mir[bb].terminator(); let loc_map = &move_data.loc_map; - let loc = Location { block: bb, index: statements_len }; + let loc = Location { block: bb, statement_index: statements_len }; debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", term, loc, &loc_map[loc]); let bits_per_block = self.bits_per_block(ctxt); diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 111646912ade3..57ec27aca9b04 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -9,7 +9,7 @@ // except according to those terms. use indexed_set::IdxSetBuf; -use super::gather_moves::{MoveData, MovePathIndex, MovePathContent, Location}; +use super::gather_moves::{MoveData, MovePathIndex, MovePathContent}; use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use super::dataflow::{DataflowResults}; use super::{drop_flag_effects_for_location, on_all_children_bits}; @@ -146,9 +146,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { dead: self.flow_uninits.sets().on_entry_set_for(loc.block.index()) .to_owned(), }; - for stmt in 0..loc.index { + for stmt in 0..loc.statement_index { data.apply_location(self.tcx, self.mir, self.env, - Location { block: loc.block, index: stmt }); + Location { block: loc.block, statement_index: stmt }); } data } @@ -226,7 +226,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let init_data = self.initialization_data_at(Location { block: bb, - index: data.statements.len() + statement_index: data.statements.len() }); let path = self.move_data().rev_lookup.find(location); @@ -249,7 +249,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn elaborate_drops(&mut self) { for (bb, data) in self.mir.basic_blocks().iter_enumerated() { - let loc = Location { block: bb, index: data.statements.len() }; + let loc = Location { block: bb, statement_index: data.statements.len() }; let terminator = data.terminator(); let resume_block = self.patch.resume_block(); @@ -359,9 +359,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { unwind: Some(unwind) }, bb); on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| { - self.set_drop_flag(Location { block: target, index: 0 }, + self.set_drop_flag(Location { block: target, statement_index: 0 }, child, DropFlagState::Present); - self.set_drop_flag(Location { block: unwind, index: 0 }, + self.set_drop_flag(Location { block: unwind, statement_index: 0 }, child, DropFlagState::Present); }); } @@ -741,7 +741,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let drop_block = self.drop_block(c); if update_drop_flag { self.set_drop_flag( - Location { block: drop_block, index: 0 }, + Location { block: drop_block, statement_index: 0 }, c.path, DropFlagState::Absent ); @@ -924,7 +924,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn drop_flags_on_init(&mut self) { - let loc = Location { block: START_BLOCK, index: 0 }; + let loc = Location { block: START_BLOCK, statement_index: 0 }; let span = self.patch.source_info_for_location(self.mir, loc).span; let false_ = self.constant_bool(span, false); for flag in self.drop_flags.values() { @@ -939,7 +939,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } = data.terminator().kind { assert!(!self.patch.is_patched(bb)); - let loc = Location { block: tgt, index: 0 }; + let loc = Location { block: tgt, statement_index: 0 }; let path = self.move_data().rev_lookup.find(lv); on_all_children_bits( self.tcx, self.mir, self.move_data(), path, @@ -950,7 +950,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn drop_flags_for_args(&mut self) { - let loc = Location { block: START_BLOCK, index: 0 }; + let loc = Location { block: START_BLOCK, statement_index: 0 }; super::drop_flag_effects_for_function_entry( self.tcx, self.mir, self.env, |path, ds| { self.set_drop_flag(loc, path, ds); @@ -990,7 +990,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } } } - let loc = Location { block: bb, index: i }; + let loc = Location { block: bb, statement_index: i }; super::drop_flag_effects_for_location( self.tcx, self.mir, self.env, loc, |path, ds| { if ds == DropFlagState::Absent || allow_initializations { @@ -1008,7 +1008,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } = data.terminator().kind { assert!(!self.patch.is_patched(bb)); - let loc = Location { block: bb, index: data.statements.len() }; + let loc = Location { block: bb, statement_index: data.statements.len() }; let path = self.move_data().rev_lookup.find(lv); on_all_children_bits( self.tcx, self.mir, self.move_data(), path, diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 8ae40e71bee58..01bf8ed0e4b57 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -160,8 +160,8 @@ impl Index for LocMap { type Output = [MoveOutIndex]; fn index(&self, index: Location) -> &Self::Output { assert!(index.block.index() < self.map.len()); - assert!(index.index < self.map[index.block.index()].len()); - &self.map[index.block.index()][index.index] + assert!(index.statement_index < self.map[index.block.index()].len()); + &self.map[index.block.index()][index.statement_index] } } @@ -200,21 +200,6 @@ impl fmt::Debug for MoveOut { } } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Location { - /// block where action is located - pub block: BasicBlock, - /// index within above block; statement when < statments.len) or - /// the terminator (when = statements.len). - pub index: usize, -} - -impl fmt::Debug for Location { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}[{}]", self.block, self.index) - } -} - #[derive(Debug)] pub struct MovePathData<'tcx> { move_paths: Vec>, @@ -569,7 +554,7 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD }; for (i, stmt) in bb_data.statements.iter().enumerate() { - let source = Location { block: bb, index: i }; + let source = Location { block: bb, statement_index: i }; match stmt.kind { StatementKind::Assign(ref lval, ref rval) => { bb_ctxt.builder.create_move_path(lval); @@ -631,14 +616,14 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD TerminatorKind::Return => { let source = Location { block: bb, - index: bb_data.statements.len() }; + statement_index: bb_data.statements.len() }; debug!("gather_moves Return on_move_out_lval return {:?}", source); bb_ctxt.on_move_out_lval(SK::Return, &Lvalue::ReturnPointer, source); } TerminatorKind::If { ref cond, targets: _ } => { let source = Location { block: bb, - index: bb_data.statements.len() }; + statement_index: bb_data.statements.len() }; bb_ctxt.on_operand(SK::If, cond, source); } @@ -669,7 +654,7 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD TerminatorKind::Drop { ref location, target: _, unwind: _ } => { let source = Location { block: bb, - index: bb_data.statements.len() }; + statement_index: bb_data.statements.len() }; bb_ctxt.on_move_out_lval(SK::Drop, location, source); } TerminatorKind::DropAndReplace { ref location, ref value, .. } => { @@ -677,12 +662,12 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD bb_ctxt.path_map.fill_to(assigned_path.index()); let source = Location { block: bb, - index: bb_data.statements.len() }; + statement_index: bb_data.statements.len() }; bb_ctxt.on_operand(SK::Use, value, source); } TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => { let source = Location { block: bb, - index: bb_data.statements.len() }; + statement_index: bb_data.statements.len() }; bb_ctxt.on_operand(SK::CallFn, func, source); for arg in args { debug!("gather_moves Call on_operand {:?} {:?}", arg, source); @@ -757,7 +742,7 @@ impl<'b, 'tcx: 'b> BlockContext<'b, 'tcx> { stmt_kind: StmtKind, lval: &Lvalue<'tcx>, source: Location) { - let i = source.index; + let i = source.statement_index; let index = MoveOutIndex::new(self.moves.len()); let path = self.builder.move_path_for(lval); diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index dbee0ea9b00e9..31380c6f71c99 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -19,7 +19,7 @@ use rustc::hir; use rustc::hir::intravisit::{FnKind}; use rustc::mir::repr; -use rustc::mir::repr::{BasicBlock, BasicBlockData, Mir, Statement, Terminator}; +use rustc::mir::repr::{BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; @@ -35,7 +35,7 @@ use self::dataflow::{DataflowOperator}; use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults}; use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use self::dataflow::{DefinitelyInitializedLvals}; -use self::gather_moves::{MoveData, MovePathIndex, Location}; +use self::gather_moves::{MoveData, MovePathIndex}; use self::gather_moves::{MovePathContent, MovePathData}; fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option> { @@ -367,7 +367,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( } let block = &mir[loc.block]; - match block.statements.get(loc.index) { + match block.statements.get(loc.statement_index) { Some(stmt) => match stmt.kind { repr::StatementKind::SetDiscriminant{ .. } => { span_bug!(stmt.source_info.span, "SetDiscrimant should not exist during borrowck"); diff --git a/src/librustc_borrowck/borrowck/mir/patch.rs b/src/librustc_borrowck/borrowck/mir/patch.rs index 417e719a9dcb9..52cd1a9f949bf 100644 --- a/src/librustc_borrowck/borrowck/mir/patch.rs +++ b/src/librustc_borrowck/borrowck/mir/patch.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::gather_moves::Location; use rustc::ty::Ty; use rustc::mir::repr::*; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -89,7 +88,7 @@ impl<'tcx> MirPatch<'tcx> { }; Location { block: bb, - index: offset + statement_index: offset } } @@ -149,12 +148,12 @@ impl<'tcx> MirPatch<'tcx> { } debug!("MirPatch: adding statement {:?} at loc {:?}+{}", stmt, loc, delta); - loc.index += delta; + loc.statement_index += delta; let source_info = Self::source_info_for_index( &mir[loc.block], loc ); mir[loc.block].statements.insert( - loc.index, Statement { + loc.statement_index, Statement { source_info: source_info, kind: stmt }); @@ -163,7 +162,7 @@ impl<'tcx> MirPatch<'tcx> { } pub fn source_info_for_index(data: &BasicBlockData, loc: Location) -> SourceInfo { - match data.statements.get(loc.index) { + match data.statements.get(loc.statement_index) { Some(stmt) => stmt.source_info, None => data.terminator().source_info } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b0335258b4041..ccbc4de82fb63 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -42,6 +42,7 @@ use rustc_const_math::ConstInt; use rustc::mir; use rustc::mir::visit::MutVisitor; +use rustc::mir::repr::Location; use std::cell::Cell; use std::io; @@ -846,7 +847,7 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v> for MirDefIdAndSpanTranslator<'cdata, 'codemap> { - fn visit_def_id(&mut self, def_id: &mut DefId) { + fn visit_def_id(&mut self, def_id: &mut DefId, _: Location) { *def_id = translate_def_id(self.crate_metadata, *def_id); } diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 83f8c3b42c850..026a79b32b8f7 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -13,7 +13,7 @@ //! Routines for manipulating the control-flow graph. -use build::{CFG, Location}; +use build::CFG; use rustc::mir::repr::*; impl<'tcx> CFG<'tcx> { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 26eb782a73b00..59d6cf1185969 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -101,16 +101,6 @@ pub struct ScopeAuxiliary { pub postdoms: Vec, } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] -pub struct Location { - /// the location is within this block - pub block: BasicBlock, - - /// the location is the start of the this statement; or, if `statement_index` - /// == num-statements, then the start of the terminator. - pub statement_index: usize, -} - pub type ScopeAuxiliaryVec = IndexVec; /////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index c58491096b94f..d46a7b2bb9506 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use build::{Location, ScopeAuxiliaryVec, ScopeId}; +use build::{ScopeAuxiliaryVec, ScopeId}; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::mir::repr::*; diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 818f060ed445c..32fddd293cacd 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -19,7 +19,10 @@ use rustc::mir::transform::{Pass, MirPass, MirSource}; pub struct NoLandingPads; impl<'tcx> MutVisitor<'tcx> for NoLandingPads { - fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) { + fn visit_terminator(&mut self, + bb: BasicBlock, + terminator: &mut Terminator<'tcx>, + location: Location) { match terminator.kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume | @@ -37,7 +40,7 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads { unwind.take(); }, } - self.super_terminator(bb, terminator); + self.super_terminator(bb, terminator, location); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 21b406c3bf5c9..f864f1678f236 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -28,11 +28,10 @@ use rustc::mir::traversal::ReversePostorder; use rustc::ty::TyCtxt; use syntax_pos::Span; -use build::Location; - use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use std::mem; +use std::usize; /// State of a temporary during collection and promotion. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -77,13 +76,12 @@ pub enum Candidate { struct TempCollector { temps: IndexVec, - location: Location, span: Span } impl<'tcx> Visitor<'tcx> for TempCollector { - fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) { - self.super_lvalue(lvalue, context); + fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext, location: Location) { + self.super_lvalue(lvalue, context, location); if let Lvalue::Temp(index) = *lvalue { // Ignore drops, if the temp gets promoted, // then it's constant and thus drop is noop. @@ -101,7 +99,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector { LvalueContext::Store | LvalueContext::Call => { *temp = TempState::Defined { - location: self.location, + location: location, uses: 0 }; return; @@ -126,27 +124,11 @@ impl<'tcx> Visitor<'tcx> for TempCollector { fn visit_source_info(&mut self, source_info: &SourceInfo) { self.span = source_info.span; } - - fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>) { - assert_eq!(self.location.block, bb); - self.super_statement(bb, statement); - self.location.statement_index += 1; - } - - fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) { - self.location.statement_index = 0; - self.location.block = bb; - self.super_basic_block_data(bb, data); - } } pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec { let mut collector = TempCollector { temps: IndexVec::from_elem(TempState::Undefined, &mir.temp_decls), - location: Location { - block: START_BLOCK, - statement_index: 0 - }, span: mir.span }; for (bb, data) in rpo { @@ -266,9 +248,15 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // Then, recurse for components in the Rvalue or Call. if stmt_idx < no_stmts { - self.visit_rvalue(rvalue.as_mut().unwrap()); + self.visit_rvalue(rvalue.as_mut().unwrap(), Location { + block: bb, + statement_index: stmt_idx + }); } else { - self.visit_terminator_kind(bb, call.as_mut().unwrap()); + self.visit_terminator_kind(bb, call.as_mut().unwrap(), Location { + block: bb, + statement_index: no_stmts + }); } let new_temp = self.promoted.temp_decls.push(TempDecl { @@ -327,7 +315,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } } }; - self.visit_rvalue(&mut rvalue); + self.visit_rvalue(&mut rvalue, Location{ + block: BasicBlock::new(0), + statement_index: usize::MAX + }); self.assign(Lvalue::ReturnPointer, rvalue, span); self.source.promoted.push(self.promoted); } @@ -335,11 +326,14 @@ 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) { + fn visit_lvalue(&mut self, + lvalue: &mut Lvalue<'tcx>, + context: LvalueContext, + location: Location) { if let Lvalue::Temp(ref mut temp) = *lvalue { *temp = self.promote_temp(*temp); } - self.super_lvalue(lvalue, context); + self.super_lvalue(lvalue, context, location); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index bcdc0d2ea3f9d..840befe603eee 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -36,8 +36,7 @@ use syntax_pos::Span; use std::collections::hash_map::Entry; use std::fmt; - -use build::Location; +use std::usize; use super::promote_consts::{self, Candidate, TempState}; @@ -147,7 +146,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { return_qualif: Option, qualif: Qualif, const_fn_arg_vars: BitVector, - location: Location, temp_promotion_state: IndexVec, promotion_candidates: Vec } @@ -178,10 +176,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { return_qualif: None, qualif: Qualif::empty(), const_fn_arg_vars: BitVector::new(mir.var_decls.len()), - location: Location { - block: START_BLOCK, - statement_index: 0 - }, temp_promotion_state: temps, promotion_candidates: vec![] } @@ -293,7 +287,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } /// Assign the current qualification to the given destination. - fn assign(&mut self, dest: &Lvalue<'tcx>) { + fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) { let qualif = self.qualif; let span = self.span; let store = |slot: &mut Option| { @@ -331,7 +325,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // This must be an explicit assignment. _ => { // Catch more errors in the destination. - self.visit_lvalue(dest, LvalueContext::Store); + self.visit_lvalue(dest, LvalueContext::Store, location); self.statement_like(); } } @@ -399,7 +393,10 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { self.qualif = Qualif::NOT_CONST; for index in 0..mir.var_decls.len() { if !self.const_fn_arg_vars.contains(index) { - self.assign(&Lvalue::Var(Var::new(index))); + self.assign(&Lvalue::Var(Var::new(index)), Location { + block: bb, + statement_index: usize::MAX, + }); } } @@ -445,7 +442,7 @@ 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_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) { + fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext, location: Location) { match *lvalue { Lvalue::Arg(_) => { self.add(Qualif::FN_ARGUMENT); @@ -477,7 +474,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } Lvalue::Projection(ref proj) => { self.nest(|this| { - this.super_lvalue(lvalue, context); + this.super_lvalue(lvalue, context, location); match proj.elem { ProjectionElem::Deref => { if !this.try_consume() { @@ -527,11 +524,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } - fn visit_operand(&mut self, operand: &Operand<'tcx>) { + fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { match *operand { Operand::Consume(_) => { self.nest(|this| { - this.super_operand(operand); + this.super_operand(operand, location); this.try_consume(); }); } @@ -570,9 +567,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { // Recurse through operands and lvalues. - self.super_rvalue(rvalue); + self.super_rvalue(rvalue, location); match *rvalue { Rvalue::Use(_) | @@ -648,7 +645,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } // We might have a candidate for promotion. - let candidate = Candidate::Ref(self.location); + let candidate = Candidate::Ref(location); if self.mode == Mode::Fn || self.mode == Mode::ConstFn { if !self.qualif.intersects(Qualif::NEVER_PROMOTE) { // We can only promote direct borrows of temps. @@ -733,9 +730,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } - fn visit_terminator_kind(&mut self, bb: BasicBlock, kind: &TerminatorKind<'tcx>) { + fn visit_terminator_kind(&mut self, + bb: BasicBlock, + kind: &TerminatorKind<'tcx>, + location: Location) { if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind { - self.visit_operand(func); + self.visit_operand(func, location); let fn_ty = func.ty(self.mir, self.tcx); let (is_shuffle, is_const_fn) = match fn_ty.sty { @@ -749,7 +749,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { for (i, arg) in args.iter().enumerate() { self.nest(|this| { - this.visit_operand(arg); + this.visit_operand(arg, location); if is_shuffle && i == 2 && this.mode == Mode::Fn { let candidate = Candidate::ShuffleIndices(bb); if !this.qualif.intersects(Qualif::NEVER_PROMOTE) { @@ -827,16 +827,20 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { self.deny_drop(); } } - self.assign(dest); + self.assign(dest, location); } } else { // Qualify any operands inside other terminators. - self.super_terminator_kind(bb, kind); + self.super_terminator_kind(bb, kind, location); } } - fn visit_assign(&mut self, _: BasicBlock, dest: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) { - self.visit_rvalue(rvalue); + fn visit_assign(&mut self, + _: BasicBlock, + dest: &Lvalue<'tcx>, + rvalue: &Rvalue<'tcx>, + location: Location) { + self.visit_rvalue(rvalue, location); // Check the allowed const fn argument forms. if let (Mode::ConstFn, &Lvalue::Var(index)) = (self.mode, dest) { @@ -857,38 +861,32 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } - self.assign(dest); + self.assign(dest, location); } fn visit_source_info(&mut self, source_info: &SourceInfo) { self.span = source_info.span; } - fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>) { - assert_eq!(self.location.block, bb); + fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>, location: Location) { self.nest(|this| { this.visit_source_info(&statement.source_info); match statement.kind { StatementKind::Assign(ref lvalue, ref rvalue) => { - this.visit_assign(bb, lvalue, rvalue); + this.visit_assign(bb, lvalue, rvalue, location); } StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => {} } }); - self.location.statement_index += 1; - } - - fn visit_terminator(&mut self, bb: BasicBlock, terminator: &Terminator<'tcx>) { - assert_eq!(self.location.block, bb); - self.nest(|this| this.super_terminator(bb, terminator)); } - fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) { - self.location.statement_index = 0; - self.location.block = bb; - self.super_basic_block_data(bb, data); + fn visit_terminator(&mut self, + bb: BasicBlock, + terminator: &Terminator<'tcx>, + location: Location) { + self.nest(|this| this.super_terminator(bb, terminator, location)); } } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index bbd2a93659b0a..21d4ae595e8ac 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -68,17 +68,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { } } - fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, _context: visit::LvalueContext) { - self.sanitize_lvalue(lvalue); + fn visit_lvalue(&mut self, + lvalue: &Lvalue<'tcx>, + _context: visit::LvalueContext, + location: Location) { + self.sanitize_lvalue(lvalue, location); } - fn visit_constant(&mut self, constant: &Constant<'tcx>) { - self.super_constant(constant); + fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { + self.super_constant(constant, location); self.sanitize_type(constant, constant.ty); } - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { - self.super_rvalue(rvalue); + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { + self.super_rvalue(rvalue, location); if let Some(ty) = rvalue.ty(self.mir, self.tcx()) { self.sanitize_type(rvalue, ty); } @@ -124,7 +127,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } } - fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>) -> LvalueTy<'tcx> { + fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>, location: Location) -> LvalueTy<'tcx> { debug!("sanitize_lvalue: {:?}", lvalue); match *lvalue { Lvalue::Var(index) => LvalueTy::Ty { ty: self.mir.var_decls[index].ty }, @@ -136,14 +139,14 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { LvalueTy::Ty { ty: self.mir.return_ty } } Lvalue::Projection(ref proj) => { - let base_ty = self.sanitize_lvalue(&proj.base); + let base_ty = self.sanitize_lvalue(&proj.base, location); if let LvalueTy::Ty { ty } = base_ty { if ty.references_error() { assert!(self.errors_reported); return LvalueTy::Ty { ty: self.tcx().types.err }; } } - self.sanitize_projection(base_ty, &proj.elem, lvalue) + self.sanitize_projection(base_ty, &proj.elem, lvalue, location) } } } @@ -151,7 +154,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn sanitize_projection(&mut self, base: LvalueTy<'tcx>, pi: &LvalueElem<'tcx>, - lvalue: &Lvalue<'tcx>) + lvalue: &Lvalue<'tcx>, + location: Location) -> LvalueTy<'tcx> { debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, lvalue); let tcx = self.tcx(); @@ -168,7 +172,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } } ProjectionElem::Index(ref i) => { - self.visit_operand(i); + self.visit_operand(i, location); let index_ty = i.ty(self.mir, tcx); if index_ty != tcx.types.usize { LvalueTy::Ty { diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 76910304eebb0..c11e696302d34 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -201,6 +201,7 @@ use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::mir::repr as mir; use rustc::mir::visit as mir_visit; use rustc::mir::visit::Visitor as MirVisitor; +use rustc::mir::repr::Location; use rustc_const_eval as const_eval; @@ -446,7 +447,7 @@ struct MirNeighborCollector<'a, 'tcx: 'a> { impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { - fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>) { + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { debug!("visiting rvalue {:?}", *rvalue); match *rvalue { @@ -517,12 +518,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _ => { /* not interesting */ } } - self.super_rvalue(rvalue); + self.super_rvalue(rvalue, location); } fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, - context: mir_visit::LvalueContext) { + context: mir_visit::LvalueContext, + location: Location) { debug!("visiting lvalue {:?}", *lvalue); if let mir_visit::LvalueContext::Drop = context { @@ -537,10 +539,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty))); } - self.super_lvalue(lvalue, context); + self.super_lvalue(lvalue, context, location); } - fn visit_operand(&mut self, operand: &mir::Operand<'tcx>) { + fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { debug!("visiting operand {:?}", *operand); let callee = match *operand { @@ -620,7 +622,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { } } - self.super_operand(operand); + self.super_operand(operand, location); fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) @@ -654,7 +656,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { // we would not register drop-glues. fn visit_terminator_kind(&mut self, block: mir::BasicBlock, - kind: &mir::TerminatorKind<'tcx>) { + kind: &mir::TerminatorKind<'tcx>, + location: Location) { let tcx = self.scx.tcx(); match *kind { mir::TerminatorKind::Call { @@ -682,7 +685,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _ => { /* Nothing to do. */ } } - self.super_terminator_kind(block, kind); + self.super_terminator_kind(block, kind, location); fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 66eb78aef07b4..cfd1ec0996861 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -15,6 +15,7 @@ use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::repr as mir; use rustc::mir::repr::TerminatorKind; +use rustc::mir::repr::Location; use rustc::mir::visit::{Visitor, LvalueContext}; use rustc::mir::traversal; use common::{self, Block, BlockAndBuilder}; @@ -104,7 +105,8 @@ impl<'mir, 'bcx, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'bcx, 'tcx> { fn visit_assign(&mut self, block: mir::BasicBlock, lvalue: &mir::Lvalue<'tcx>, - rvalue: &mir::Rvalue<'tcx>) { + rvalue: &mir::Rvalue<'tcx>, + location: Location) { debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue); if let Some(index) = self.mir.local_index(lvalue) { @@ -113,15 +115,16 @@ impl<'mir, 'bcx, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'bcx, 'tcx> { self.mark_as_lvalue(index); } } else { - self.visit_lvalue(lvalue, LvalueContext::Store); + self.visit_lvalue(lvalue, LvalueContext::Store, location); } - self.visit_rvalue(rvalue); + self.visit_rvalue(rvalue, location); } fn visit_terminator_kind(&mut self, block: mir::BasicBlock, - kind: &mir::TerminatorKind<'tcx>) { + kind: &mir::TerminatorKind<'tcx>, + location: Location) { match *kind { mir::TerminatorKind::Call { func: mir::Operand::Constant(mir::Constant { @@ -133,18 +136,19 @@ impl<'mir, 'bcx, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'bcx, 'tcx> { // is not guaranteed to be statically dominated by the // definition of x, so x must always be in an alloca. if let mir::Operand::Consume(ref lvalue) = args[0] { - self.visit_lvalue(lvalue, LvalueContext::Drop); + self.visit_lvalue(lvalue, LvalueContext::Drop, location); } } _ => {} } - self.super_terminator_kind(block, kind); + self.super_terminator_kind(block, kind, location); } fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, - context: LvalueContext) { + context: LvalueContext, + location: Location) { debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context); // Allow uses of projections of immediate pair fields. @@ -196,11 +200,11 @@ impl<'mir, 'bcx, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'bcx, 'tcx> { // 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); + return self.visit_lvalue(&proj.base, LvalueContext::Consume, location); } } - self.super_lvalue(lvalue, context); + self.super_lvalue(lvalue, context, location); } } diff --git a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs index 604933d40a12c..f7b046b30cad7 100644 --- a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs +++ b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs @@ -19,7 +19,7 @@ extern crate rustc_const_math; extern crate syntax; use rustc::mir::transform::{self, MirPass, MirSource}; -use rustc::mir::repr::{Mir, Literal}; +use rustc::mir::repr::{Mir, Literal, Location}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; use rustc::middle::const_val::ConstVal; @@ -40,7 +40,7 @@ impl<'tcx> MirPass<'tcx> for Pass { struct Visitor; impl<'tcx> MutVisitor<'tcx> for Visitor { - fn visit_literal(&mut self, literal: &mut Literal<'tcx>) { + fn visit_literal(&mut self, literal: &mut Literal<'tcx>, _: Location) { if let Literal::Value { ref mut value } = *literal { if let ConstVal::Integral(ConstInt::I32(ref mut i @ 11)) = *value { *i = 42;