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,
}
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);
}
}
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,
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);
}
}
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,
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);
}
}
}
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);
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);
}
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);
}
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);
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));
}
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));
}
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));
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));
}
}
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);
}
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) => {
}
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);
}
}
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(_) |
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 => {
}
self.visit_ty(ty);
}
ProjectionElem::Index(ref $($mutability)* operand) => {
- self.visit_operand(operand);
+ self.visit_operand(operand, location);
}
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
}
fn super_constant(&mut self,
- constant: & $($mutability)* Constant<'tcx>) {
+ constant: & $($mutability)* Constant<'tcx>,
+ location: Location) {
let Constant {
ref $($mutability)* span,
ref $($mutability)* ty,
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,
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: _ } => {}
}
make_mir_visitor!(MutVisitor,mut);
#[derive(Copy, Clone, Debug)]
- pub enum LvalueContext {
+ pub enum LvalueContext<'tcx> {
// Appears as LHS of an assignment
Store,
Inspect,
// Being borrowed
- Borrow { region: Region, kind: BorrowKind },
+ Borrow { region: &'tcx Region, kind: BorrowKind },
// Being sliced -- this should be same as being borrowed, probably
Slice { from_start: usize, from_end: usize },
// 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};
use super::{DropFlagState, MoveDataParamEnv};
use super::patch::MirPatch;
use rustc::ty::{self, Ty, TyCtxt};
- use rustc::ty::subst::{Subst, Substs};
+ use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::mir::repr::*;
use rustc::mir::transform::{Pass, MirPass, MirSource};
use rustc::middle::const_val::ConstVal;
use syntax_pos::Span;
use std::fmt;
+ use std::iter;
use std::u32;
pub struct ElaborateDrops;
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
}
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);
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();
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);
});
}
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
);
let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil()));
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e));
- let substs = Substs::new(tcx, vec![ty], vec![]);
+ let substs = Substs::new(tcx, iter::once(Kind::from(ty)));
let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs);
self.patch.new_block(BasicBlockData {
}
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() {
} = 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,
}
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);
}
}
}
- 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 {
} = 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,
use std::collections::hash_map::Entry;
use std::fmt;
-
-use build::Location;
+use std::usize;
use super::promote_consts::{self, Candidate, TempState};
return_qualif: Option<Qualif>,
qualif: Qualif,
const_fn_arg_vars: BitVector,
- location: Location,
temp_promotion_state: IndexVec<Temp, TempState>,
promotion_candidates: Vec<Candidate>
}
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![]
}
}
/// 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>| {
// 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();
}
}
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,
+ });
}
}
/// 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);
}
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() {
}
}
- 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();
});
}
if let Literal::Item { def_id, substs } = constant.literal {
// Don't peek inside generic (associated) constants.
- if !substs.types.is_empty() {
+ if substs.types().next().is_some() {
self.add_type(constant.ty);
} else {
let qualif = qualify_const_item_cached(self.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(_) |
}
// 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.
}
}
- 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 {
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) {
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) {
}
}
- 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));
}
}