use syntax::source_map::CompilerDesugaringKind;
use super::borrow_set::BorrowData;
-use super::{Context, MirBorrowckCtxt};
+use super::{MirBorrowckCtxt};
use super::{InitializationRequiringAction, PrefixSet};
use crate::dataflow::drop_flag_effects;
use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex};
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
pub(super) fn report_use_of_moved_or_uninitialized(
&mut self,
- context: Context,
+ location: Location,
desired_action: InitializationRequiringAction,
(moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span),
mpi: MovePathIndex,
) {
debug!(
- "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} \
+ "report_use_of_moved_or_uninitialized: location={:?} desired_action={:?} \
moved_place={:?} used_place={:?} span={:?} mpi={:?}",
- context, desired_action, moved_place, used_place, span, mpi
+ location, desired_action, moved_place, used_place, span, mpi
);
- let use_spans = self.move_spans(moved_place, context.loc)
- .or_else(|| self.borrow_spans(span, context.loc));
+ let use_spans = self.move_spans(moved_place, location)
+ .or_else(|| self.borrow_spans(span, location));
let span = use_spans.args_or_use();
- let move_site_vec = self.get_moved_indexes(context, mpi);
+ let move_site_vec = self.get_moved_indexes(location, mpi);
debug!(
"report_use_of_moved_or_uninitialized: move_site_vec={:?}",
move_site_vec
);
self.add_moved_or_invoked_closure_note(
- context.loc,
+ location,
used_place,
&mut err,
);
pub(super) fn report_move_out_while_borrowed(
&mut self,
- context: Context,
+ location: Location,
(place, span): (&Place<'tcx>, Span),
borrow: &BorrowData<'tcx>,
) {
debug!(
- "report_move_out_while_borrowed: context={:?} place={:?} span={:?} borrow={:?}",
- context, place, span, borrow
+ "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}",
+ location, place, span, borrow
);
let tcx = self.infcx.tcx;
let value_msg = match self.describe_place(place) {
let borrow_spans = self.retrieve_borrow_spans(borrow);
let borrow_span = borrow_spans.args_or_use();
- let move_spans = self.move_spans(place, context.loc);
+ let move_spans = self.move_spans(place, location);
let span = move_spans.args_or_use();
let mut err = tcx.cannot_move_when_borrowed(
);
self.explain_why_borrow_contains_point(
- context,
+ location,
borrow,
None,
).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span));
pub(super) fn report_use_while_mutably_borrowed(
&mut self,
- context: Context,
+ location: Location,
(place, _span): (&Place<'tcx>, Span),
borrow: &BorrowData<'tcx>,
) -> DiagnosticBuilder<'cx> {
// Conflicting borrows are reported separately, so only check for move
// captures.
- let use_spans = self.move_spans(place, context.loc);
+ let use_spans = self.move_spans(place, location);
let span = use_spans.var_or_use();
let mut err = tcx.cannot_use_when_mutably_borrowed(
format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe())
});
- self.explain_why_borrow_contains_point(context, borrow, None)
+ self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
err
}
pub(super) fn report_conflicting_borrow(
&mut self,
- context: Context,
+ location: Location,
(place, span): (&Place<'tcx>, Span),
gen_borrow_kind: BorrowKind,
issued_borrow: &BorrowData<'tcx>,
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
let issued_span = issued_spans.args_or_use();
- let borrow_spans = self.borrow_spans(span, context.loc);
+ let borrow_spans = self.borrow_spans(span, location);
let span = borrow_spans.args_or_use();
let container_name = if issued_spans.for_generator() || borrow_spans.for_generator() {
let (desc_place, msg_place, msg_borrow, union_type_name) =
self.describe_place_for_conflicting_borrow(place, &issued_borrow.borrowed_place);
- let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None);
+ let explanation = self.explain_why_borrow_contains_point(location, issued_borrow, None);
let second_borrow_desc = if explanation.is_explained() {
"second "
} else {
/// `Drop::drop` with an aliasing borrow.)
pub(super) fn report_borrowed_value_does_not_live_long_enough(
&mut self,
- context: Context,
+ location: Location,
borrow: &BorrowData<'tcx>,
place_span: (&Place<'tcx>, Span),
kind: Option<WriteKind>,
"report_borrowed_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}\
)",
- context, borrow, place_span, kind
+ location, borrow, place_span, kind
);
let drop_span = place_span.1;
// destructor conflict.
if !borrow.borrowed_place.is_prefix_of(place_span.0) {
self.report_borrow_conflicts_with_destructor(
- context, borrow, place_span, kind, dropped_ty,
+ location, borrow, place_span, kind, dropped_ty,
);
return;
}
let place_desc = self.describe_place(&borrow.borrowed_place);
let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
- let explanation = self.explain_why_borrow_contains_point(context, &borrow, kind_place);
+ let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
let err = match (place_desc, explanation) {
(Some(_), _) if self.is_place_thread_local(root_place) => {
},
) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
(Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
- context,
+ location,
&name,
&scope_tree,
&borrow,
explanation,
),
(None, explanation) => self.report_temporary_value_does_not_live_long_enough(
- context,
+ location,
&scope_tree,
&borrow,
drop_span,
fn report_local_value_does_not_live_long_enough(
&mut self,
- context: Context,
+ location: Location,
name: &str,
scope_tree: &'tcx ScopeTree,
borrow: &BorrowData<'tcx>,
"report_local_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
)",
- context, name, scope_tree, borrow, drop_span, borrow_spans
+ location, name, scope_tree, borrow, drop_span, borrow_spans
);
let borrow_span = borrow_spans.var_or_use();
fn report_borrow_conflicts_with_destructor(
&mut self,
- context: Context,
+ location: Location,
borrow: &BorrowData<'tcx>,
(place, drop_span): (&Place<'tcx>, Span),
kind: Option<WriteKind>,
"report_borrow_conflicts_with_destructor(\
{:?}, {:?}, ({:?}, {:?}), {:?}\
)",
- context, borrow, place, drop_span, kind,
+ location, borrow, place, drop_span, kind,
);
let borrow_spans = self.retrieve_borrow_spans(borrow);
// Only give this note and suggestion if they could be relevant.
let explanation =
- self.explain_why_borrow_contains_point(context, borrow, kind.map(|k| (k, place)));
+ self.explain_why_borrow_contains_point(location, borrow, kind.map(|k| (k, place)));
match explanation {
BorrowExplanation::UsedLater { .. }
| BorrowExplanation::UsedLaterWhenDropped { .. } => {
fn report_temporary_value_does_not_live_long_enough(
&mut self,
- context: Context,
+ location: Location,
scope_tree: &'tcx ScopeTree,
borrow: &BorrowData<'tcx>,
drop_span: Span,
"report_temporary_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}\
)",
- context, scope_tree, borrow, drop_span, proper_span
+ location, scope_tree, borrow, drop_span, proper_span
);
if let BorrowExplanation::MustBeValidFor {
err
}
- fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec<MoveSite> {
+ fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec<MoveSite> {
let mir = self.mir;
let mut stack = Vec::new();
- stack.extend(mir.predecessor_locations(context.loc).map(|predecessor| {
- let is_back_edge = context.loc.dominates(predecessor, &self.dominators);
+ stack.extend(mir.predecessor_locations(location).map(|predecessor| {
+ let is_back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge)
}));
pub(super) fn report_illegal_mutation_of_borrowed(
&mut self,
- context: Context,
+ location: Location,
(place, span): (&Place<'tcx>, Span),
loan: &BorrowData<'tcx>,
) {
format!("borrow occurs due to use{}", loan_spans.describe()),
);
- self.explain_why_borrow_contains_point(context, loan, None)
+ self.explain_why_borrow_contains_point(location, loan, None)
.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
err.buffer(&mut self.errors_buffer);
/// assignment to `x.f`).
pub(super) fn report_illegal_reassignment(
&mut self,
- _context: Context,
+ _location: Location,
(place, span): (&Place<'tcx>, Span),
assigned_span: Span,
err_place: &Place<'tcx>,
// Convert any reservation warnings into lints.
let reservation_warnings = mem::replace(&mut mbcx.reservation_warnings, Default::default());
- for (_, (place, span, context, bk, borrow)) in reservation_warnings {
- let mut initial_diag = mbcx.report_conflicting_borrow(context, (&place, span), bk, &borrow);
+ for (_, (place, span, location, bk, borrow)) in reservation_warnings {
+ let mut initial_diag =
+ mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow);
let lint_root = if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data {
- let scope = mbcx.mir.source_info(context.loc).scope;
+ let scope = mbcx.mir.source_info(location).scope;
vsi[scope].lint_root
} else {
id
/// for the activation of the borrow.
reservation_warnings: FxHashMap<
BorrowIndex,
- (Place<'tcx>, Span, Context, BorrowKind, BorrowData<'tcx>)
+ (Place<'tcx>, Span, Location, BorrowKind, BorrowData<'tcx>)
>,
/// This field keeps track of move errors that are to be reported for given move indicies.
///
match stmt.kind {
StatementKind::Assign(ref lhs, ref rhs) => {
self.consume_rvalue(
- ContextKind::AssignRhs.new(location),
- (rhs, span),
location,
+ (rhs, span),
flow_state,
);
self.mutate_place(
- ContextKind::AssignLhs.new(location),
+ location,
(lhs, span),
Shallow(None),
JustWrite,
// match x {};
// from compiling.
self.check_if_path_or_subpath_is_moved(
- ContextKind::FakeRead.new(location),
+ location,
InitializationRequiringAction::Use,
(place, span),
flow_state,
variant_index: _,
} => {
self.mutate_place(
- ContextKind::SetDiscrim.new(location),
+ location,
(place, span),
Shallow(None),
JustWrite,
);
}
StatementKind::InlineAsm(ref asm) => {
- let context = ContextKind::InlineAsm.new(location);
for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
if o.is_indirect {
// FIXME(eddyb) indirect inline asm outputs should
// be encoded through MIR place derefs instead.
self.access_place(
- context,
+ location,
(output, o.span),
(Deep, Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
flow_state,
);
self.check_if_path_or_subpath_is_moved(
- context,
+ location,
InitializationRequiringAction::Use,
(output, o.span),
flow_state,
);
} else {
self.mutate_place(
- context,
+ location,
(output, o.span),
if o.is_rw { Deep } else { Shallow(None) },
if o.is_rw { WriteAndRead } else { JustWrite },
}
}
for (_, input) in asm.inputs.iter() {
- self.consume_operand(context, (input, span), flow_state);
+ self.consume_operand(location, (input, span), flow_state);
}
}
StatementKind::Nop
}
StatementKind::StorageDead(local) => {
self.access_place(
- ContextKind::StorageDead.new(location),
+ location,
(&Place::Base(PlaceBase::Local(local)), span),
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
values: _,
targets: _,
} => {
- self.consume_operand(ContextKind::SwitchInt.new(loc), (discr, span), flow_state);
+ self.consume_operand(loc, (discr, span), flow_state);
}
TerminatorKind::Drop {
location: ref drop_place,
loc, term, drop_place, drop_place_ty, span);
self.access_place(
- ContextKind::Drop.new(loc),
+ loc,
(drop_place, span),
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
unwind: _,
} => {
self.mutate_place(
- ContextKind::DropAndReplace.new(loc),
+ loc,
(drop_place, span),
Deep,
JustWrite,
flow_state,
);
self.consume_operand(
- ContextKind::DropAndReplace.new(loc),
+ loc,
(new_value, span),
flow_state,
);
cleanup: _,
from_hir_call: _,
} => {
- self.consume_operand(ContextKind::CallOperator.new(loc), (func, span), flow_state);
+ self.consume_operand(loc, (func, span), flow_state);
for arg in args {
self.consume_operand(
- ContextKind::CallOperand.new(loc),
+ loc,
(arg, span),
flow_state,
);
}
if let Some((ref dest, _ /*bb*/)) = *destination {
self.mutate_place(
- ContextKind::CallDest.new(loc),
+ loc,
(dest, span),
Deep,
JustWrite,
target: _,
cleanup: _,
} => {
- self.consume_operand(ContextKind::Assert.new(loc), (cond, span), flow_state);
+ self.consume_operand(loc, (cond, span), flow_state);
use rustc::mir::interpret::InterpError::BoundsCheck;
if let BoundsCheck { ref len, ref index } = *msg {
- self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
- self.consume_operand(ContextKind::Assert.new(loc), (index, span), flow_state);
+ self.consume_operand(loc, (len, span), flow_state);
+ self.consume_operand(loc, (index, span), flow_state);
}
}
resume: _,
drop: _,
} => {
- self.consume_operand(ContextKind::Yield.new(loc), (value, span), flow_state);
+ self.consume_operand(loc, (value, span), flow_state);
if self.movable_generator {
// Look for any active borrows to locals
flow_state.with_outgoing_borrows(|borrows| {
for i in borrows {
let borrow = &borrow_set[i];
- let context = ContextKind::StorageDead.new(loc);
- self.check_for_invalidation_at_exit(context, borrow, span);
+ self.check_for_invalidation_at_exit(loc, borrow, span);
}
});
}
/// Returns `true` if an error is reported.
fn access_place(
&mut self,
- context: Context,
+ location: Location,
place_span: (&Place<'tcx>, Span),
kind: (AccessDepth, ReadOrWrite),
is_local_mutation_allowed: LocalMutationIsAllowed,
rw,
is_local_mutation_allowed,
flow_state,
- context.loc,
+ location,
);
let conflict_error =
- self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
+ self.check_access_for_conflict(location, place_span, sd, rw, flow_state);
if let (Activation(_, borrow_idx), true) = (kind.1, conflict_error) {
// Suppress this warning when there's an error being emited for the
fn check_access_for_conflict(
&mut self,
- context: Context,
+ location: Location,
place_span: (&Place<'tcx>, Span),
sd: AccessDepth,
rw: ReadOrWrite,
flow_state: &Flows<'cx, 'gcx, 'tcx>,
) -> bool {
debug!(
- "check_access_for_conflict(context={:?}, place_span={:?}, sd={:?}, rw={:?})",
- context, place_span, sd, rw,
+ "check_access_for_conflict(location={:?}, place_span={:?}, sd={:?}, rw={:?})",
+ location, place_span, sd, rw,
);
let mut error_reported = false;
let tcx = self.infcx.tcx;
let mir = self.mir;
- let location = self.location_table.start_index(context.loc);
+ let location_table = self.location_table.start_index(location);
let borrow_set = self.borrow_set.clone();
each_borrow_involving_path(
self,
tcx,
mir,
- context,
+ location,
(sd, place_span.0),
&borrow_set,
- flow_state.borrows_in_scope(location),
+ flow_state.borrows_in_scope(location_table),
|this, borrow_index, borrow| match (rw, borrow.kind) {
// Obviously an activation is compatible with its own
// reservation (or even prior activating uses of same
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
// Reading from mere reservations of mutable-borrows is OK.
- if !is_active(&this.dominators, borrow, context.loc) {
+ if !is_active(&this.dominators, borrow, location) {
assert!(allow_two_phase_borrow(borrow.kind));
return Control::Continue;
}
error_reported = true;
match kind {
ReadKind::Copy => {
- this.report_use_while_mutably_borrowed(context, place_span, borrow)
+ this.report_use_while_mutably_borrowed(location, place_span, borrow)
.buffer(&mut this.errors_buffer);
}
ReadKind::Borrow(bk) => {
- this.report_conflicting_borrow(context, place_span, bk, borrow)
+ this.report_conflicting_borrow(location, place_span, bk, borrow)
.buffer(&mut this.errors_buffer);
}
}
| (Reservation(WriteKind::MutableBorrow(bk)), BorrowKind::Shared) if {
tcx.migrate_borrowck()
} => {
- let bi = this.borrow_set.location_map[&context.loc];
+ let bi = this.borrow_set.location_map[&location];
debug!(
"recording invalid reservation of place: {:?} with \
borrow index {:?} as warning",
// checking was otherwise successful.
this.reservation_warnings.insert(
bi,
- (place_span.0.clone(), place_span.1, context, bk, borrow.clone()),
+ (place_span.0.clone(), place_span.1, location, bk, borrow.clone()),
);
// Don't suppress actual errors.
error_reported = true;
match kind {
WriteKind::MutableBorrow(bk) => {
- this.report_conflicting_borrow(context, place_span, bk, borrow)
+ this.report_conflicting_borrow(location, place_span, bk, borrow)
.buffer(&mut this.errors_buffer);
}
WriteKind::StorageDeadOrDrop => {
this.report_borrowed_value_does_not_live_long_enough(
- context,
+ location,
borrow,
place_span,
Some(kind))
}
WriteKind::Mutate => {
- this.report_illegal_mutation_of_borrowed(context, place_span, borrow)
+ this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
}
WriteKind::Move => {
- this.report_move_out_while_borrowed(context, place_span, borrow)
+ this.report_move_out_while_borrowed(location, place_span, borrow)
}
}
Control::Break
fn mutate_place(
&mut self,
- context: Context,
+ location: Location,
place_span: (&Place<'tcx>, Span),
kind: AccessDepth,
mode: MutateMode,
match mode {
MutateMode::WriteAndRead => {
self.check_if_path_or_subpath_is_moved(
- context,
+ location,
InitializationRequiringAction::Update,
place_span,
flow_state,
);
}
MutateMode::JustWrite => {
- self.check_if_assigned_path_is_moved(context, place_span, flow_state);
+ self.check_if_assigned_path_is_moved(location, place_span, flow_state);
}
}
if let Mutability::Not = self.mir.local_decls[local].mutability {
// check for reassignments to immutable local variables
self.check_if_reassignment_to_immutable_state(
- context,
+ location,
local,
place_span,
flow_state,
// Otherwise, use the normal access permission rules.
self.access_place(
- context,
+ location,
place_span,
(kind, Write(WriteKind::Mutate)),
LocalMutationIsAllowed::No,
fn consume_rvalue(
&mut self,
- context: Context,
+ location: Location,
(rvalue, span): (&Rvalue<'tcx>, Span),
- _location: Location,
flow_state: &Flows<'cx, 'gcx, 'tcx>,
) {
match *rvalue {
};
self.access_place(
- context,
+ location,
(place, span),
access_kind,
LocalMutationIsAllowed::No,
};
self.check_if_path_or_subpath_is_moved(
- context,
+ location,
action,
(place, span),
flow_state,
| Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
- self.consume_operand(context, (operand, span), flow_state)
+ self.consume_operand(location, (operand, span), flow_state)
}
Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
_ => unreachable!(),
};
self.access_place(
- context,
+ location,
(place, span),
(Shallow(af), Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
flow_state,
);
self.check_if_path_or_subpath_is_moved(
- context,
+ location,
InitializationRequiringAction::Use,
(place, span),
flow_state,
Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2)
| Rvalue::CheckedBinaryOp(_bin_op, ref operand1, ref operand2) => {
- self.consume_operand(context, (operand1, span), flow_state);
- self.consume_operand(context, (operand2, span), flow_state);
+ self.consume_operand(location, (operand1, span), flow_state);
+ self.consume_operand(location, (operand2, span), flow_state);
}
Rvalue::NullaryOp(_op, _ty) => {
}
for operand in operands {
- self.consume_operand(context, (operand, span), flow_state);
+ self.consume_operand(location, (operand, span), flow_state);
}
}
}
fn consume_operand(
&mut self,
- context: Context,
+ location: Location,
(operand, span): (&Operand<'tcx>, Span),
flow_state: &Flows<'cx, 'gcx, 'tcx>,
) {
// copy of place: check if this is "copy of frozen path"
// (FIXME: see check_loans.rs)
self.access_place(
- context,
+ location,
(place, span),
(Deep, Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
// Finally, check if path was already moved.
self.check_if_path_or_subpath_is_moved(
- context,
+ location,
InitializationRequiringAction::Use,
(place, span),
flow_state,
Operand::Move(ref place) => {
// move of place: check if this is move of already borrowed path
self.access_place(
- context,
+ location,
(place, span),
(Deep, Write(WriteKind::Move)),
LocalMutationIsAllowed::Yes,
// Finally, check if path was already moved.
self.check_if_path_or_subpath_is_moved(
- context,
+ location,
InitializationRequiringAction::Use,
(place, span),
flow_state,
/// exits
fn check_for_invalidation_at_exit(
&mut self,
- context: Context,
+ location: Location,
borrow: &BorrowData<'tcx>,
span: Span,
) {
// of just a span here.
let span = self.infcx.tcx.sess.source_map().end_point(span);
self.report_borrowed_value_does_not_live_long_enough(
- context,
+ location,
borrow,
(place, span),
None,
});
self.access_place(
- ContextKind::Activation.new(location),
+ location,
(&borrow.borrowed_place, span),
(
Deep,
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
fn check_if_reassignment_to_immutable_state(
&mut self,
- context: Context,
+ location: Location,
local: Local,
place_span: (&Place<'tcx>, Span),
flow_state: &Flows<'cx, 'gcx, 'tcx>,
let init = &self.move_data.inits[init_index];
let span = init.span(&self.mir);
self.report_illegal_reassignment(
- context, place_span, span, place_span.0
+ location, place_span, span, place_span.0
);
}
}
fn check_if_full_path_is_moved(
&mut self,
- context: Context,
+ location: Location,
desired_action: InitializationRequiringAction,
place_span: (&Place<'tcx>, Span),
flow_state: &Flows<'cx, 'gcx, 'tcx>,
Ok((prefix, mpi)) => {
if maybe_uninits.contains(mpi) {
self.report_use_of_moved_or_uninitialized(
- context,
+ location,
desired_action,
(prefix, place_span.0, place_span.1),
mpi,
fn check_if_path_or_subpath_is_moved(
&mut self,
- context: Context,
+ location: Location,
desired_action: InitializationRequiringAction,
place_span: (&Place<'tcx>, Span),
flow_state: &Flows<'cx, 'gcx, 'tcx>,
// must have been initialized for the use to be sound.
// 6. Move of `a.b.c` then reinit of `a.b.c.d`, use of `a.b.c.d`
- self.check_if_full_path_is_moved(context, desired_action, place_span, flow_state);
+ self.check_if_full_path_is_moved(location, desired_action, place_span, flow_state);
// A move of any shallow suffix of `place` also interferes
// with an attempt to use `place`. This is scenario 3 above.
if let Some(mpi) = self.move_path_for_place(place_span.0) {
if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) {
self.report_use_of_moved_or_uninitialized(
- context,
+ location,
desired_action,
(place_span.0, place_span.0, place_span.1),
child_mpi,
fn check_if_assigned_path_is_moved(
&mut self,
- context: Context,
+ location: Location,
(place, span): (&Place<'tcx>, Span),
flow_state: &Flows<'cx, 'gcx, 'tcx>,
) {
// assigning to (*P) requires P to be initialized
ProjectionElem::Deref => {
self.check_if_full_path_is_moved(
- context, InitializationRequiringAction::Use,
+ location, InitializationRequiringAction::Use,
(base, span), flow_state);
// (base initialized; no need to
// recur further)
}
ProjectionElem::Subslice { .. } => {
- panic!("we don't allow assignments to subslices, context: {:?}",
- context);
+ panic!("we don't allow assignments to subslices, location: {:?}",
+ location);
}
ProjectionElem::Field(..) => {
match base.ty(self.mir, tcx).ty.sty {
ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved(
- context, InitializationRequiringAction::Assignment,
+ location, InitializationRequiringAction::Assignment,
(base, span), flow_state);
// (base initialized; no need to
// Once `let s; s.x = V; read(s.x);`,
// is allowed, remove this match arm.
ty::Adt(..) | ty::Tuple(..) => {
- check_parent_of_field(self, context, base, span, flow_state);
+ check_parent_of_field(self, location, base, span, flow_state);
if let Some(local) = place.base_local() {
// rust-lang/rust#21232,
fn check_parent_of_field<'cx, 'gcx, 'tcx>(
this: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
- context: Context,
+ location: Location,
base: &Place<'tcx>,
span: Span,
flow_state: &Flows<'cx, 'gcx, 'tcx>,
if def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| {
this.move_data.moves[*moi].source.is_predecessor_of(
- context.loc, this.mir,
+ location, this.mir,
)
}) {
return;
}
this.report_use_of_moved_or_uninitialized(
- context,
+ location,
InitializationRequiringAction::PartialAssignment,
(prefix, base, span),
mpi,
// Subtle: this is an upvar
// reference, so it looks like
// `self.foo` -- we want to double
- // check that the context `*self`
+ // check that the location `*self`
// is mutable (i.e., this is not a
// `Fn` closure). But if that
// check succeeds, we want to
/// will also be disjoint.
Disjoint,
}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-struct Context {
- kind: ContextKind,
- loc: Location,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum ContextKind {
- Activation,
- AssignLhs,
- AssignRhs,
- SetDiscrim,
- InlineAsm,
- SwitchInt,
- Drop,
- DropAndReplace,
- CallOperator,
- CallOperand,
- CallDest,
- Assert,
- Yield,
- FakeRead,
- StorageDead,
-}
-
-impl ContextKind {
- fn new(self, loc: Location) -> Context {
- Context {
- kind: self,
- loc,
- }
- }
-}
use crate::borrow_check::error_reporting::UseSpans;
use crate::borrow_check::nll::region_infer::{Cause, RegionName};
use crate::borrow_check::nll::ConstraintDescription;
-use crate::borrow_check::{Context, MirBorrowckCtxt, WriteKind};
+use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
use rustc::mir::{
CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
/// Returns structured explanation for *why* the borrow contains the
- /// point from `context`. This is key for the "3-point errors"
+ /// point from `location`. This is key for the "3-point errors"
/// [described in the NLL RFC][d].
///
/// # Parameters
///
/// - `borrow`: the borrow in question
- /// - `context`: where the borrow occurs
+ /// - `location`: where the borrow occurs
/// - `kind_place`: if Some, this describes the statement that triggered the error.
/// - first half is the kind of write, if any, being performed
/// - second half is the place being accessed
/// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
&self,
- context: Context,
+ location: Location,
borrow: &BorrowData<'tcx>,
kind_place: Option<(WriteKind, &Place<'tcx>)>,
) -> BorrowExplanation {
debug!(
- "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
- context, borrow, kind_place
+ "explain_why_borrow_contains_point(location={:?}, borrow={:?}, kind_place={:?})",
+ location, borrow, kind_place
);
let regioncx = &self.nonlexical_regioncx;
borrow_region_vid
);
- let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, context.loc);
+ let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, location);
debug!(
"explain_why_borrow_contains_point: region_sub={:?}",
region_sub
);
- match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
+ match find_use::find(mir, regioncx, tcx, region_sub, location) {
Some(Cause::LiveVar(local, location)) => {
let span = mir.source_info(location).span;
let spans = self
.move_spans(&Place::Base(PlaceBase::Local(local)), location)
.or_else(|| self.borrow_spans(span, location));
- let borrow_location = context.loc;
+ let borrow_location = location;
if self.is_use_in_later_iteration_of_loop(borrow_location, location) {
let later_use = self.later_use_kind(borrow, spans, location);
BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1)
use crate::borrow_check::{JustWrite, WriteAndRead};
use crate::borrow_check::{AccessDepth, Deep, Shallow};
use crate::borrow_check::{ReadOrWrite, Activation, Read, Reservation, Write};
-use crate::borrow_check::{Context, ContextKind};
use crate::borrow_check::{LocalMutationIsAllowed, MutateMode};
use crate::borrow_check::ArtificialField;
use crate::borrow_check::{ReadKind, WriteKind};
match statement.kind {
StatementKind::Assign(ref lhs, ref rhs) => {
self.consume_rvalue(
- ContextKind::AssignRhs.new(location),
+ location,
rhs,
);
self.mutate_place(
- ContextKind::AssignLhs.new(location),
+ location,
lhs,
Shallow(None),
JustWrite
variant_index: _,
} => {
self.mutate_place(
- ContextKind::SetDiscrim.new(location),
+ location,
place,
Shallow(None),
JustWrite,
);
}
StatementKind::InlineAsm(ref asm) => {
- let context = ContextKind::InlineAsm.new(location);
for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
if o.is_indirect {
// FIXME(eddyb) indirect inline asm outputs should
// be encoded through MIR place derefs instead.
self.access_place(
- context,
+ location,
output,
(Deep, Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
);
} else {
self.mutate_place(
- context,
+ location,
output,
if o.is_rw { Deep } else { Shallow(None) },
if o.is_rw { WriteAndRead } else { JustWrite },
}
}
for (_, input) in asm.inputs.iter() {
- self.consume_operand(context, input);
+ self.consume_operand(location, input);
}
}
StatementKind::Nop |
}
StatementKind::StorageDead(local) => {
self.access_place(
- ContextKind::StorageDead.new(location),
+ location,
&Place::Base(PlaceBase::Local(local)),
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
values: _,
targets: _,
} => {
- self.consume_operand(ContextKind::SwitchInt.new(location), discr);
+ self.consume_operand(location, discr);
}
TerminatorKind::Drop {
location: ref drop_place,
unwind: _,
} => {
self.access_place(
- ContextKind::Drop.new(location),
+ location,
drop_place,
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
unwind: _,
} => {
self.mutate_place(
- ContextKind::DropAndReplace.new(location),
+ location,
drop_place,
Deep,
JustWrite,
);
self.consume_operand(
- ContextKind::DropAndReplace.new(location),
+ location,
new_value,
);
}
cleanup: _,
from_hir_call: _,
} => {
- self.consume_operand(ContextKind::CallOperator.new(location), func);
+ self.consume_operand(location, func);
for arg in args {
- self.consume_operand(ContextKind::CallOperand.new(location), arg);
+ self.consume_operand(location, arg);
}
if let Some((ref dest, _ /*bb*/)) = *destination {
self.mutate_place(
- ContextKind::CallDest.new(location),
+ location,
dest,
Deep,
JustWrite,
target: _,
cleanup: _,
} => {
- self.consume_operand(ContextKind::Assert.new(location), cond);
+ self.consume_operand(location, cond);
use rustc::mir::interpret::InterpError::BoundsCheck;
if let BoundsCheck { ref len, ref index } = *msg {
- self.consume_operand(ContextKind::Assert.new(location), len);
- self.consume_operand(ContextKind::Assert.new(location), index);
+ self.consume_operand(location, len);
+ self.consume_operand(location, index);
}
}
TerminatorKind::Yield {
resume,
drop: _,
} => {
- self.consume_operand(ContextKind::Yield.new(location), value);
+ self.consume_operand(location, value);
// Invalidate all borrows of local places
let borrow_set = self.borrow_set.clone();
/// Simulates mutation of a place.
fn mutate_place(
&mut self,
- context: Context,
+ location: Location,
place: &Place<'tcx>,
kind: AccessDepth,
_mode: MutateMode,
) {
self.access_place(
- context,
+ location,
place,
(kind, Write(WriteKind::Mutate)),
LocalMutationIsAllowed::ExceptUpvars,
/// Simulates consumption of an operand.
fn consume_operand(
&mut self,
- context: Context,
+ location: Location,
operand: &Operand<'tcx>,
) {
match *operand {
Operand::Copy(ref place) => {
self.access_place(
- context,
+ location,
place,
(Deep, Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
}
Operand::Move(ref place) => {
self.access_place(
- context,
+ location,
place,
(Deep, Write(WriteKind::Move)),
LocalMutationIsAllowed::Yes,
// Simulates consumption of an rvalue
fn consume_rvalue(
&mut self,
- context: Context,
+ location: Location,
rvalue: &Rvalue<'tcx>,
) {
match *rvalue {
};
self.access_place(
- context,
+ location,
place,
access_kind,
LocalMutationIsAllowed::No,
| Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
- self.consume_operand(context, operand)
+ self.consume_operand(location, operand)
}
Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
_ => unreachable!(),
};
self.access_place(
- context,
+ location,
place,
(Shallow(af), Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2)
| Rvalue::CheckedBinaryOp(_bin_op, ref operand1, ref operand2) => {
- self.consume_operand(context, operand1);
- self.consume_operand(context, operand2);
+ self.consume_operand(location, operand1);
+ self.consume_operand(location, operand2);
}
Rvalue::NullaryOp(_op, _ty) => {
Rvalue::Aggregate(_, ref operands) => {
for operand in operands {
- self.consume_operand(context, operand);
+ self.consume_operand(location, operand);
}
}
}
/// Simulates an access to a place.
fn access_place(
&mut self,
- context: Context,
+ location: Location,
place: &Place<'tcx>,
kind: (AccessDepth, ReadOrWrite),
_is_local_mutation_allowed: LocalMutationIsAllowed,
) {
let (sd, rw) = kind;
// note: not doing check_access_permissions checks because they don't generate invalidates
- self.check_access_for_conflict(context, place, sd, rw);
+ self.check_access_for_conflict(location, place, sd, rw);
}
fn check_access_for_conflict(
&mut self,
- context: Context,
+ location: Location,
place: &Place<'tcx>,
sd: AccessDepth,
rw: ReadOrWrite,
) {
debug!(
- "invalidation::check_access_for_conflict(context={:?}, place={:?}, sd={:?}, \
+ "invalidation::check_access_for_conflict(location={:?}, place={:?}, sd={:?}, \
rw={:?})",
- context,
+ location,
place,
sd,
rw,
self,
tcx,
mir,
- context,
+ location,
(sd, place),
&borrow_set.clone(),
indices,
(Read(_), BorrowKind::Unique) | (Read(_), BorrowKind::Mut { .. }) => {
// Reading from mere reservations of mutable-borrows is OK.
- if !is_active(&this.dominators, borrow, context.loc) {
+ if !is_active(&this.dominators, borrow, location) {
// If the borrow isn't active yet, reads don't invalidate it
assert!(allow_two_phase_borrow(borrow.kind));
return Control::Continue;
// Unique and mutable borrows are invalidated by reads from any
// involved path
- this.generate_invalidates(borrow_index, context.loc);
+ this.generate_invalidates(borrow_index, location);
}
(Reservation(_), _)
// Reservations count as writes since we need to check
// that activating the borrow will be OK
// FIXME(bob_twinkles) is this actually the right thing to do?
- this.generate_invalidates(borrow_index, context.loc);
+ this.generate_invalidates(borrow_index, location);
}
}
Control::Continue
});
self.access_place(
- ContextKind::Activation.new(location),
+ location,
&borrow.borrowed_place,
(
Deep,
use crate::borrow_check::borrow_set::{BorrowSet, BorrowData, TwoPhaseActivation};
use crate::borrow_check::places_conflict;
-use crate::borrow_check::Context;
use crate::borrow_check::AccessDepth;
use crate::dataflow::indexes::BorrowIndex;
use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
s: &mut S,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
- _context: Context,
+ _location: Location,
access_place: (AccessDepth, &Place<'tcx>),
borrow_set: &BorrowSet<'tcx>,
candidates: I,