Remove Context and ContextKind
This commit is contained in:
parent
6cc24f2603
commit
99ebb7a517
@ -22,7 +22,7 @@ use syntax_pos::Span;
|
||||
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};
|
||||
@ -42,22 +42,22 @@ struct MoveSite {
|
||||
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
|
||||
@ -125,7 +125,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
);
|
||||
|
||||
self.add_moved_or_invoked_closure_note(
|
||||
context.loc,
|
||||
location,
|
||||
used_place,
|
||||
&mut err,
|
||||
);
|
||||
@ -261,13 +261,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
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) {
|
||||
@ -282,7 +282,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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(
|
||||
@ -304,7 +304,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
);
|
||||
|
||||
self.explain_why_borrow_contains_point(
|
||||
context,
|
||||
location,
|
||||
borrow,
|
||||
None,
|
||||
).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span));
|
||||
@ -313,7 +313,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
pub(super) fn report_use_while_mutably_borrowed(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
(place, _span): (&Place<'tcx>, Span),
|
||||
borrow: &BorrowData<'tcx>,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
@ -324,7 +324,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// 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(
|
||||
@ -343,14 +343,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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>,
|
||||
@ -358,7 +358,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, '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() {
|
||||
@ -370,7 +370,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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 {
|
||||
@ -671,7 +671,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
/// `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>,
|
||||
@ -680,7 +680,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
"report_borrowed_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}, {:?}, {:?}\
|
||||
)",
|
||||
context, borrow, place_span, kind
|
||||
location, borrow, place_span, kind
|
||||
);
|
||||
|
||||
let drop_span = place_span.1;
|
||||
@ -719,7 +719,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
// 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;
|
||||
}
|
||||
@ -728,7 +728,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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) => {
|
||||
@ -784,7 +784,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
},
|
||||
) => 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,
|
||||
@ -793,7 +793,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
explanation,
|
||||
),
|
||||
(None, explanation) => self.report_temporary_value_does_not_live_long_enough(
|
||||
context,
|
||||
location,
|
||||
&scope_tree,
|
||||
&borrow,
|
||||
drop_span,
|
||||
@ -808,7 +808,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
fn report_local_value_does_not_live_long_enough(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
name: &str,
|
||||
scope_tree: &'tcx ScopeTree,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
@ -820,7 +820,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, '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();
|
||||
@ -914,7 +914,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
fn report_borrow_conflicts_with_destructor(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
(place, drop_span): (&Place<'tcx>, Span),
|
||||
kind: Option<WriteKind>,
|
||||
@ -924,7 +924,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
"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);
|
||||
@ -957,7 +957,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// 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 { .. } => {
|
||||
@ -998,7 +998,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
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,
|
||||
@ -1010,7 +1010,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
"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 {
|
||||
@ -1246,12 +1246,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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)
|
||||
}));
|
||||
|
||||
@ -1348,7 +1348,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
pub(super) fn report_illegal_mutation_of_borrowed(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
(place, span): (&Place<'tcx>, Span),
|
||||
loan: &BorrowData<'tcx>,
|
||||
) {
|
||||
@ -1386,7 +1386,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, '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);
|
||||
@ -1400,7 +1400,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
/// 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>,
|
||||
|
@ -302,11 +302,12 @@ fn do_mir_borrowck<'a, 'gcx, '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
|
||||
@ -483,7 +484,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
/// 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.
|
||||
///
|
||||
@ -559,14 +560,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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,
|
||||
@ -585,7 +585,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
// match x {};
|
||||
// from compiling.
|
||||
self.check_if_path_or_subpath_is_moved(
|
||||
ContextKind::FakeRead.new(location),
|
||||
location,
|
||||
InitializationRequiringAction::Use,
|
||||
(place, span),
|
||||
flow_state,
|
||||
@ -596,7 +596,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
variant_index: _,
|
||||
} => {
|
||||
self.mutate_place(
|
||||
ContextKind::SetDiscrim.new(location),
|
||||
location,
|
||||
(place, span),
|
||||
Shallow(None),
|
||||
JustWrite,
|
||||
@ -604,27 +604,26 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
);
|
||||
}
|
||||
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 },
|
||||
@ -633,7 +632,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
}
|
||||
}
|
||||
for (_, input) in asm.inputs.iter() {
|
||||
self.consume_operand(context, (input, span), flow_state);
|
||||
self.consume_operand(location, (input, span), flow_state);
|
||||
}
|
||||
}
|
||||
StatementKind::Nop
|
||||
@ -645,7 +644,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
}
|
||||
StatementKind::StorageDead(local) => {
|
||||
self.access_place(
|
||||
ContextKind::StorageDead.new(location),
|
||||
location,
|
||||
(&Place::Base(PlaceBase::Local(local)), span),
|
||||
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
||||
LocalMutationIsAllowed::Yes,
|
||||
@ -677,7 +676,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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,
|
||||
@ -702,7 +701,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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,
|
||||
@ -716,14 +715,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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,
|
||||
);
|
||||
@ -735,17 +734,17 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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,
|
||||
@ -760,11 +759,11 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -773,7 +772,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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
|
||||
@ -796,8 +795,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -955,7 +953,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
/// 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,
|
||||
@ -994,10 +992,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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
|
||||
@ -1018,30 +1016,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
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
|
||||
@ -1075,7 +1073,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
(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;
|
||||
}
|
||||
@ -1083,11 +1081,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1098,7 +1096,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
| (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",
|
||||
@ -1111,7 +1109,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
// 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.
|
||||
@ -1143,21 +1141,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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
|
||||
@ -1170,7 +1168,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
fn mutate_place(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
place_span: (&Place<'tcx>, Span),
|
||||
kind: AccessDepth,
|
||||
mode: MutateMode,
|
||||
@ -1180,14 +1178,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1198,7 +1196,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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,
|
||||
@ -1209,7 +1207,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// Otherwise, use the normal access permission rules.
|
||||
self.access_place(
|
||||
context,
|
||||
location,
|
||||
place_span,
|
||||
(kind, Write(WriteKind::Mutate)),
|
||||
LocalMutationIsAllowed::No,
|
||||
@ -1219,9 +1217,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
fn consume_rvalue(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
(rvalue, span): (&Rvalue<'tcx>, Span),
|
||||
_location: Location,
|
||||
flow_state: &Flows<'cx, 'gcx, 'tcx>,
|
||||
) {
|
||||
match *rvalue {
|
||||
@ -1242,7 +1239,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
self.access_place(
|
||||
context,
|
||||
location,
|
||||
(place, span),
|
||||
access_kind,
|
||||
LocalMutationIsAllowed::No,
|
||||
@ -1256,7 +1253,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
self.check_if_path_or_subpath_is_moved(
|
||||
context,
|
||||
location,
|
||||
action,
|
||||
(place, span),
|
||||
flow_state,
|
||||
@ -1267,7 +1264,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
| 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) => {
|
||||
@ -1277,14 +1274,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
_ => 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,
|
||||
@ -1293,8 +1290,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
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) => {
|
||||
@ -1326,7 +1323,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
for operand in operands {
|
||||
self.consume_operand(context, (operand, span), flow_state);
|
||||
self.consume_operand(location, (operand, span), flow_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1407,7 +1404,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
fn consume_operand(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
(operand, span): (&Operand<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'gcx, 'tcx>,
|
||||
) {
|
||||
@ -1416,7 +1413,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'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,
|
||||
@ -1425,7 +1422,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// Finally, check if path was already moved.
|
||||
self.check_if_path_or_subpath_is_moved(
|
||||
context,
|
||||
location,
|
||||
InitializationRequiringAction::Use,
|
||||
(place, span),
|
||||
flow_state,
|
||||
@ -1434,7 +1431,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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,
|
||||
@ -1443,7 +1440,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// Finally, check if path was already moved.
|
||||
self.check_if_path_or_subpath_is_moved(
|
||||
context,
|
||||
location,
|
||||
InitializationRequiringAction::Use,
|
||||
(place, span),
|
||||
flow_state,
|
||||
@ -1457,7 +1454,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
/// exits
|
||||
fn check_for_invalidation_at_exit(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
@ -1513,7 +1510,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
// 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,
|
||||
@ -1558,7 +1555,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
});
|
||||
|
||||
self.access_place(
|
||||
ContextKind::Activation.new(location),
|
||||
location,
|
||||
(&borrow.borrowed_place, span),
|
||||
(
|
||||
Deep,
|
||||
@ -1577,7 +1574,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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>,
|
||||
@ -1590,14 +1587,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'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>,
|
||||
@ -1644,7 +1641,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'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,
|
||||
@ -1665,7 +1662,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
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>,
|
||||
@ -1687,7 +1684,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'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.
|
||||
@ -1702,7 +1699,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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,
|
||||
@ -1753,7 +1750,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
fn check_if_assigned_path_is_moved(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
(place, span): (&Place<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'gcx, 'tcx>,
|
||||
) {
|
||||
@ -1781,7 +1778,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'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)
|
||||
@ -1789,8 +1786,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
ProjectionElem::Subslice { .. } => {
|
||||
panic!("we don't allow assignments to subslices, context: {:?}",
|
||||
context);
|
||||
panic!("we don't allow assignments to subslices, location: {:?}",
|
||||
location);
|
||||
}
|
||||
|
||||
ProjectionElem::Field(..) => {
|
||||
@ -1801,7 +1798,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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
|
||||
@ -1813,7 +1810,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
// 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,
|
||||
@ -1841,7 +1838,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
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>,
|
||||
@ -1907,7 +1904,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'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;
|
||||
@ -1916,7 +1913,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
this.report_use_of_moved_or_uninitialized(
|
||||
context,
|
||||
location,
|
||||
InitializationRequiringAction::PartialAssignment,
|
||||
(prefix, base, span),
|
||||
mpi,
|
||||
@ -2234,7 +2231,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
// 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
|
||||
@ -2331,37 +2328,3 @@ enum Overlap {
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::borrow_check::borrow_set::BorrowData;
|
||||
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,
|
||||
@ -209,13 +209,13 @@ impl BorrowExplanation {
|
||||
|
||||
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
|
||||
@ -223,13 +223,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
/// [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;
|
||||
@ -242,20 +242,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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)
|
||||
|
@ -3,7 +3,6 @@ use crate::borrow_check::location::LocationTable;
|
||||
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};
|
||||
@ -66,12 +65,12 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
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
|
||||
@ -85,27 +84,26 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
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 },
|
||||
@ -113,7 +111,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
}
|
||||
}
|
||||
for (_, input) in asm.inputs.iter() {
|
||||
self.consume_operand(context, input);
|
||||
self.consume_operand(location, input);
|
||||
}
|
||||
}
|
||||
StatementKind::Nop |
|
||||
@ -125,7 +123,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
}
|
||||
StatementKind::StorageDead(local) => {
|
||||
self.access_place(
|
||||
ContextKind::StorageDead.new(location),
|
||||
location,
|
||||
&Place::Base(PlaceBase::Local(local)),
|
||||
(Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
|
||||
LocalMutationIsAllowed::Yes,
|
||||
@ -150,7 +148,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
values: _,
|
||||
targets: _,
|
||||
} => {
|
||||
self.consume_operand(ContextKind::SwitchInt.new(location), discr);
|
||||
self.consume_operand(location, discr);
|
||||
}
|
||||
TerminatorKind::Drop {
|
||||
location: ref drop_place,
|
||||
@ -158,7 +156,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
unwind: _,
|
||||
} => {
|
||||
self.access_place(
|
||||
ContextKind::Drop.new(location),
|
||||
location,
|
||||
drop_place,
|
||||
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
|
||||
LocalMutationIsAllowed::Yes,
|
||||
@ -171,13 +169,13 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
unwind: _,
|
||||
} => {
|
||||
self.mutate_place(
|
||||
ContextKind::DropAndReplace.new(location),
|
||||
location,
|
||||
drop_place,
|
||||
Deep,
|
||||
JustWrite,
|
||||
);
|
||||
self.consume_operand(
|
||||
ContextKind::DropAndReplace.new(location),
|
||||
location,
|
||||
new_value,
|
||||
);
|
||||
}
|
||||
@ -188,13 +186,13 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
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,
|
||||
@ -208,11 +206,11 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
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 {
|
||||
@ -220,7 +218,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
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();
|
||||
@ -264,13 +262,13 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
/// 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,
|
||||
@ -280,13 +278,13 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
/// 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,
|
||||
@ -294,7 +292,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
}
|
||||
Operand::Move(ref place) => {
|
||||
self.access_place(
|
||||
context,
|
||||
location,
|
||||
place,
|
||||
(Deep, Write(WriteKind::Move)),
|
||||
LocalMutationIsAllowed::Yes,
|
||||
@ -307,7 +305,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
// Simulates consumption of an rvalue
|
||||
fn consume_rvalue(
|
||||
&mut self,
|
||||
context: Context,
|
||||
location: Location,
|
||||
rvalue: &Rvalue<'tcx>,
|
||||
) {
|
||||
match *rvalue {
|
||||
@ -328,7 +326,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
};
|
||||
|
||||
self.access_place(
|
||||
context,
|
||||
location,
|
||||
place,
|
||||
access_kind,
|
||||
LocalMutationIsAllowed::No,
|
||||
@ -339,7 +337,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
| 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) => {
|
||||
@ -349,7 +347,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.access_place(
|
||||
context,
|
||||
location,
|
||||
place,
|
||||
(Shallow(af), Read(ReadKind::Copy)),
|
||||
LocalMutationIsAllowed::No,
|
||||
@ -358,8 +356,8 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
|
||||
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) => {
|
||||
@ -367,7 +365,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
|
||||
Rvalue::Aggregate(_, ref operands) => {
|
||||
for operand in operands {
|
||||
self.consume_operand(context, operand);
|
||||
self.consume_operand(location, operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -376,27 +374,27 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
/// 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,
|
||||
@ -409,7 +407,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
self,
|
||||
tcx,
|
||||
mir,
|
||||
context,
|
||||
location,
|
||||
(sd, place),
|
||||
&borrow_set.clone(),
|
||||
indices,
|
||||
@ -435,7 +433,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
|
||||
(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;
|
||||
@ -443,7 +441,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
|
||||
// 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(_), _)
|
||||
@ -453,7 +451,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
// 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
|
||||
@ -485,7 +483,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
||||
});
|
||||
|
||||
self.access_place(
|
||||
ContextKind::Activation.new(location),
|
||||
location,
|
||||
&borrow.borrowed_place,
|
||||
(
|
||||
Deep,
|
||||
|
@ -1,6 +1,5 @@
|
||||
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};
|
||||
@ -27,7 +26,7 @@ pub(super) fn each_borrow_involving_path<'a, 'tcx, 'gcx: 'tcx, F, I, S> (
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user