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:
commit
b7e2157dba
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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: _ } => {}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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>;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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::*;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user