Auto merge of #35542 - scottcarr:visitor_refactor, r=nikomatsakis

[MIR] track Location in MirVisitor, combine Location

All the users of MirVisitor::visit_statement implement their own statement index tracking.  This PR move the tracking into MirVisitor itself.

Also, there were 2 separate implementations of Location that were identical.  This PR eliminates one of them.
This commit is contained in:
bors 2016-08-26 19:05:11 -07:00 committed by GitHub
commit b7e2157dba
18 changed files with 278 additions and 254 deletions

View File

@ -1239,3 +1239,14 @@ impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> {
type Item = BasicBlock;
type Iter = IntoIter<BasicBlock>;
}
#[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,
}

View File

@ -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: _ } => {}
}

View File

@ -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);

View File

@ -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,

View File

@ -160,8 +160,8 @@ impl Index<Location> 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<MovePath<'tcx>>,
@ -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);

View File

@ -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<P<MetaItem>> {
@ -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");

View File

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

View File

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

View File

@ -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> {

View File

@ -101,16 +101,6 @@ pub struct ScopeAuxiliary {
pub postdoms: Vec<Location>,
}
#[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<ScopeId, ScopeAuxiliary>;
///////////////////////////////////////////////////////////////////////////

View File

@ -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::*;

View File

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

View File

@ -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<Temp, TempState>,
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<Temp, TempState> {
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);
}
}

View File

@ -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: Qualif,
const_fn_arg_vars: BitVector,
location: Location,
temp_promotion_state: IndexVec<Temp, TempState>,
promotion_candidates: Vec<Candidate>
}
@ -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<Qualif>| {
@ -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));
}
}

View File

@ -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 {

View File

@ -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,

View File

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

View File

@ -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;