1
Fork 0

Ran RustFmt on the file

This commit is contained in:
Rusty Blitzerr 2018-09-27 19:10:29 -07:00
parent c9865b1c37
commit 2ac6cdf6a1

View file

@ -8,22 +8,22 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use borrow_check::WriteKind;
use borrow_check::prefixes::IsPrefixOf;
use borrow_check::nll::explain_borrow::BorrowExplanation; use borrow_check::nll::explain_borrow::BorrowExplanation;
use borrow_check::prefixes::IsPrefixOf;
use borrow_check::WriteKind;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::middle::region::ScopeTree; use rustc::middle::region::ScopeTree;
use rustc::mir::{ use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, FakeReadCause, Field, Local, self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, FakeReadCause, Field, Local,
LocalDecl, LocalKind, Location, Operand, Place, PlaceProjection, ProjectionElem, Rvalue, LocalDecl, LocalKind, Location, Operand, Place, PlaceProjection, ProjectionElem, Rvalue,
Statement, StatementKind, TerminatorKind, VarBindingForm, Statement, StatementKind, TerminatorKind, VarBindingForm,
}; };
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::ty; use rustc::ty;
use rustc::util::ppaux::with_highlight_region_for_bound_region;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc::util::ppaux::with_highlight_region_for_bound_region;
use syntax_pos::Span; use syntax_pos::Span;
use super::borrow_set::BorrowData; use super::borrow_set::BorrowData;
@ -45,12 +45,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
) { ) {
debug!( debug!(
"report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \ "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \
span={:?} mpi={:?}", span={:?} mpi={:?}",
context, desired_action, place, span, mpi context, desired_action, place, span, mpi
); );
let use_spans = self let use_spans = self.move_spans(place, context.loc)
.move_spans(place, context.loc)
.or_else(|| self.borrow_spans(span, context.loc)); .or_else(|| self.borrow_spans(span, context.loc));
let span = use_spans.args_or_use(); let span = use_spans.args_or_use();
@ -60,7 +59,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
if mois.is_empty() { if mois.is_empty() {
let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap();
if self.uninitialized_error_reported.contains(&root_place.clone()) { if self.uninitialized_error_reported
.contains(&root_place.clone())
{
debug!( debug!(
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed", "report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
root_place root_place
@ -77,8 +78,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let mut err = self.infcx.tcx.cannot_act_on_uninitialized_variable( let mut err = self.infcx.tcx.cannot_act_on_uninitialized_variable(
span, span,
desired_action.as_noun(), desired_action.as_noun(),
&self &self.describe_place_with_options(place, IncludingDowncast(true))
.describe_place_with_options(place, IncludingDowncast(true))
.unwrap_or("_".to_owned()), .unwrap_or("_".to_owned()),
Origin::Mir, Origin::Mir,
); );
@ -92,9 +92,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
err.buffer(&mut self.errors_buffer); err.buffer(&mut self.errors_buffer);
} else { } else {
if let Some((reported_place, _)) = self.move_error_reported.get(&mois) { if let Some((reported_place, _)) = self.move_error_reported.get(&mois) {
if self.prefixes(&reported_place, PrefixSet::All).any(|p| p == place) { if self.prefixes(&reported_place, PrefixSet::All)
debug!("report_use_of_moved_or_uninitialized place: error suppressed \ .any(|p| p == place)
mois={:?}", mois); {
debug!(
"report_use_of_moved_or_uninitialized place: error suppressed \
mois={:?}",
mois
);
return; return;
} }
} }
@ -170,9 +175,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let place = &self.move_data.move_paths[mpi].place; let place = &self.move_data.move_paths[mpi].place;
if let Some(ty) = self.retrieve_type_for_place(place) { if let Some(ty) = self.retrieve_type_for_place(place) {
let note_msg = match self let note_msg = match self.describe_place_with_options(
.describe_place_with_options(place, IncludingDowncast(true)) place,
{ IncludingDowncast(true),
) {
Some(name) => format!("`{}`", name), Some(name) => format!("`{}`", name),
None => "value".to_owned(), None => "value".to_owned(),
}; };
@ -186,10 +192,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} }
} }
if let Some((_, mut old_err)) = self.move_error_reported.insert( if let Some((_, mut old_err)) =
mois, self.move_error_reported.insert(mois, (place.clone(), err))
(place.clone(), err) {
) {
// Cancel the old error so it doesn't ICE. // Cancel the old error so it doesn't ICE.
old_err.cancel(); old_err.cancel();
} }
@ -255,8 +260,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span, span,
&self.describe_place(place).unwrap_or("_".to_owned()), &self.describe_place(place).unwrap_or("_".to_owned()),
borrow_span, borrow_span,
&self &self.describe_place(&borrow.borrowed_place)
.describe_place(&borrow.borrowed_place)
.unwrap_or("_".to_owned()), .unwrap_or("_".to_owned()),
Origin::Mir, Origin::Mir,
); );
@ -299,8 +303,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"mutable", "mutable",
) { ) {
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => tcx | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => {
.cannot_reborrow_already_borrowed( tcx.cannot_reborrow_already_borrowed(
span, span,
&desc_place, &desc_place,
"", "",
@ -311,10 +315,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"", "",
None, None,
Origin::Mir, Origin::Mir,
), )
}
(BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => tcx (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => {
.cannot_mutably_borrow_multiply( tcx.cannot_mutably_borrow_multiply(
span, span,
&desc_place, &desc_place,
"", "",
@ -322,16 +327,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"", "",
None, None,
Origin::Mir, Origin::Mir,
), )
}
(BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => tcx (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => {
.cannot_uniquely_borrow_by_two_closures( tcx.cannot_uniquely_borrow_by_two_closures(
span, span,
&desc_place, &desc_place,
issued_span, issued_span,
None, None,
Origin::Mir, Origin::Mir,
), )
}
(BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _) (BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _)
| (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => { | (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => {
@ -344,10 +351,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
); );
borrow_spans.var_span_label( borrow_spans.var_span_label(
&mut err, &mut err,
format!( format!("borrow occurs due to use of `{}` in closure", desc_place),
"borrow occurs due to use of `{}` in closure",
desc_place
),
); );
err.buffer(&mut self.errors_buffer); err.buffer(&mut self.errors_buffer);
@ -365,8 +369,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Origin::Mir, Origin::Mir,
), ),
(BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => tcx (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => {
.cannot_reborrow_already_uniquely_borrowed( tcx.cannot_reborrow_already_uniquely_borrowed(
span, span,
&desc_place, &desc_place,
"", "",
@ -375,10 +379,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"", "",
None, None,
Origin::Mir, Origin::Mir,
), )
}
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => tcx (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => {
.cannot_reborrow_already_uniquely_borrowed( tcx.cannot_reborrow_already_uniquely_borrowed(
span, span,
&desc_place, &desc_place,
"", "",
@ -387,13 +392,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"", "",
None, None,
Origin::Mir, Origin::Mir,
), )
}
(BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _) (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _)
| (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => { | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => {
// Shallow borrows are uses from the user's point of view. // Shallow borrows are uses from the user's point of view.
self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow); self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow);
return return;
} }
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _)
| (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _) | (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _)
@ -447,16 +453,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
place_span: (&Place<'tcx>, Span), place_span: (&Place<'tcx>, Span),
kind: Option<WriteKind>, kind: Option<WriteKind>,
) { ) {
debug!("report_borrowed_value_does_not_live_long_enough(\ debug!(
{:?}, {:?}, {:?}, {:?}\ "report_borrowed_value_does_not_live_long_enough(\
)", {:?}, {:?}, {:?}, {:?}\
context, borrow, place_span, kind )",
context, borrow, place_span, kind
); );
let drop_span = place_span.1; let drop_span = place_span.1;
let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id); let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id);
let root_place = self let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
.prefixes(&borrow.borrowed_place, PrefixSet::All)
.last() .last()
.unwrap(); .unwrap();
@ -468,8 +474,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_ => drop_span, _ => drop_span,
}; };
if self if self.access_place_error_reported
.access_place_error_reported
.contains(&(root_place.clone(), borrow_span)) .contains(&(root_place.clone(), borrow_span))
{ {
debug!( debug!(
@ -482,8 +487,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
self.access_place_error_reported self.access_place_error_reported
.insert((root_place.clone(), borrow_span)); .insert((root_place.clone(), borrow_span));
if let StorageDeadOrDrop::Destructor(dropped_ty) if let StorageDeadOrDrop::Destructor(dropped_ty) =
= self.classify_drop_access_kind(&borrow.borrowed_place) self.classify_drop_access_kind(&borrow.borrowed_place)
{ {
// If a borrow of path `B` conflicts with drop of `D` (and // If a borrow of path `B` conflicts with drop of `D` (and
// we're not in the uninteresting case where `B` is a // we're not in the uninteresting case where `B` is a
@ -491,19 +496,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// destructor conflict. // destructor conflict.
if !borrow.borrowed_place.is_prefix_of(place_span.0) { if !borrow.borrowed_place.is_prefix_of(place_span.0) {
self.report_borrow_conflicts_with_destructor( self.report_borrow_conflicts_with_destructor(
context, context, borrow, place_span, kind, dropped_ty,
borrow,
place_span,
kind,
dropped_ty,
); );
return; return;
} }
} }
let err = match &self.describe_place(&borrow.borrowed_place) { let err = match &self.describe_place(&borrow.borrowed_place) {
Some(_) if self.is_place_thread_local(root_place) => Some(_) if self.is_place_thread_local(root_place) => {
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span), self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
}
Some(name) => self.report_local_value_does_not_live_long_enough( Some(name) => self.report_local_value_does_not_live_long_enough(
context, context,
name, name,
@ -556,7 +558,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
err.span_label( err.span_label(
borrow_span, borrow_span,
format!("`{}` would have to be valid for `{}`...", name, region_name) format!("`{}` would have to be valid for `{}`...", name, region_name),
); );
if let Some(fn_node_id) = self.infcx.tcx.hir.as_local_node_id(self.mir_def_id) { if let Some(fn_node_id) = self.infcx.tcx.hir.as_local_node_id(self.mir_def_id) {
@ -564,8 +566,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span, drop_span,
format!( format!(
"...but `{}` will be dropped here, when the function `{}` returns", "...but `{}` will be dropped here, when the function `{}` returns",
name, self.infcx.tcx.hir.name(fn_node_id), name,
) self.infcx.tcx.hir.name(fn_node_id),
),
); );
err.note( err.note(
@ -579,16 +582,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} else { } else {
err.span_label( err.span_label(
drop_span, drop_span,
format!("...but `{}` dropped here while still borrowed", name) format!("...but `{}` dropped here while still borrowed", name),
); );
} }
if let BorrowExplanation::MustBeValidFor(..) = explanation { } else { if let BorrowExplanation::MustBeValidFor(..) = explanation {
} else {
explanation.emit(self.infcx.tcx, &mut err); explanation.emit(self.infcx.tcx, &mut err);
} }
} else { } else {
err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); err.span_label(
drop_span,
format!("`{}` dropped here while still borrowed", name),
);
borrow_spans.args_span_label(&mut err, "value captured here"); borrow_spans.args_span_label(&mut err, "value captured here");
@ -616,7 +623,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_spans = self.retrieve_borrow_spans(borrow);
let borrow_span = borrow_spans.var_or_use(); let borrow_span = borrow_spans.var_or_use();
let mut err = self.infcx.tcx.cannot_borrow_across_destructor(borrow_span, Origin::Mir); let mut err = self.infcx
.tcx
.cannot_borrow_across_destructor(borrow_span, Origin::Mir);
let what_was_dropped = match self.describe_place(place) { let what_was_dropped = match self.describe_place(place) {
Some(name) => format!("`{}`", name.as_str()), Some(name) => format!("`{}`", name.as_str()),
@ -624,26 +633,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}; };
let label = match self.describe_place(&borrow.borrowed_place) { let label = match self.describe_place(&borrow.borrowed_place) {
Some(borrowed) => Some(borrowed) => format!(
format!("here, drop of {D} needs exclusive access to `{B}`, \ "here, drop of {D} needs exclusive access to `{B}`, \
because the type `{T}` implements the `Drop` trait", because the type `{T}` implements the `Drop` trait",
D=what_was_dropped, T=dropped_ty, B=borrowed), D = what_was_dropped,
None => T = dropped_ty,
format!("here is drop of {D}; whose type `{T}` implements the `Drop` trait", B = borrowed
D=what_was_dropped, T=dropped_ty), ),
None => format!(
"here is drop of {D}; whose type `{T}` implements the `Drop` trait",
D = what_was_dropped,
T = dropped_ty
),
}; };
err.span_label(drop_span, label); err.span_label(drop_span, label);
// Only give this note and suggestion if they could be relevant. // Only give this note and suggestion if they could be relevant.
let explanation = self.explain_why_borrow_contains_point( let explanation =
context, borrow, kind.map(|k| (k, place)), self.explain_why_borrow_contains_point(context, borrow, kind.map(|k| (k, place)));
);
match explanation { match explanation {
BorrowExplanation::UsedLater {..} | BorrowExplanation::UsedLater { .. }
BorrowExplanation::UsedLaterWhenDropped {..} => { | BorrowExplanation::UsedLaterWhenDropped { .. } => {
err.note("consider using a `let` binding to create a longer lived value"); err.note("consider using a `let` binding to create a longer lived value");
}, }
_ => {}, _ => {}
} }
explanation.emit(self.infcx.tcx, &mut err); explanation.emit(self.infcx.tcx, &mut err);
@ -663,9 +676,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span, borrow_span drop_span, borrow_span
); );
let mut err = self.infcx.tcx.thread_local_value_does_not_live_long_enough( let mut err = self.infcx
borrow_span, Origin::Mir .tcx
); .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir);
err.span_label( err.span_label(
borrow_span, borrow_span,
@ -693,20 +706,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
); );
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let mut err = let mut err = tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir);
tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir); err.span_label(
err.span_label(proper_span, "creates a temporary which is freed while still in use"); proper_span,
err.span_label(drop_span, "temporary value is freed at the end of this statement"); "creates a temporary which is freed while still in use",
);
err.span_label(
drop_span,
"temporary value is freed at the end of this statement",
);
let explanation = self.explain_why_borrow_contains_point(context, borrow, None); let explanation = self.explain_why_borrow_contains_point(context, borrow, None);
match explanation { match explanation {
BorrowExplanation::UsedLater(..) | BorrowExplanation::UsedLater(..)
BorrowExplanation::UsedLaterInLoop(..) | | BorrowExplanation::UsedLaterInLoop(..)
BorrowExplanation::UsedLaterWhenDropped(..) => { | BorrowExplanation::UsedLaterWhenDropped(..) => {
// Only give this note and suggestion if it could be relevant. // Only give this note and suggestion if it could be relevant.
err.note("consider using a `let` binding to create a longer lived value"); err.note("consider using a `let` binding to create a longer lived value");
}, }
_ => {}, _ => {}
} }
explanation.emit(self.infcx.tcx, &mut err); explanation.emit(self.infcx.tcx, &mut err);
@ -785,11 +803,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// check for inits // check for inits
let mut any_match = false; let mut any_match = false;
drop_flag_effects::for_location_inits(self.infcx.tcx, self.mir, self.move_data, l, |m| { drop_flag_effects::for_location_inits(
if m == mpi { self.infcx.tcx,
any_match = true; self.mir,
} self.move_data,
}); l,
|m| {
if m == mpi {
any_match = true;
}
},
);
if any_match { if any_match {
continue 'dfs; continue 'dfs;
} }
@ -829,7 +853,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
self.explain_why_borrow_contains_point(context, loan, None).emit(self.infcx.tcx, &mut err); self.explain_why_borrow_contains_point(context, loan, None)
.emit(self.infcx.tcx, &mut err);
err.buffer(&mut self.errors_buffer); err.buffer(&mut self.errors_buffer);
} }
@ -1151,7 +1176,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// the closure comes from another crate. But in that case we wouldn't // the closure comes from another crate. But in that case we wouldn't
// be borrowck'ing it, so we can just unwrap: // be borrowck'ing it, so we can just unwrap:
let node_id = self.infcx.tcx.hir.as_local_node_id(def_id).unwrap(); let node_id = self.infcx.tcx.hir.as_local_node_id(def_id).unwrap();
let freevar = self.infcx.tcx.with_freevars(node_id, |fv| fv[field.index()]); let freevar = self.infcx
.tcx
.with_freevars(node_id, |fv| fv[field.index()]);
self.infcx.tcx.hir.name(freevar.var_id()).to_string() self.infcx.tcx.hir.name(freevar.var_id()).to_string()
} }
@ -1218,35 +1245,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> { fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
match place { match place {
Place::Local(_) Place::Local(_) | Place::Static(_) | Place::Promoted(_) => {
| Place::Static(_) StorageDeadOrDrop::LocalStorageDead
| Place::Promoted(_) => StorageDeadOrDrop::LocalStorageDead, }
Place::Projection(box PlaceProjection { base, elem }) => { Place::Projection(box PlaceProjection { base, elem }) => {
let base_access = self.classify_drop_access_kind(base); let base_access = self.classify_drop_access_kind(base);
match elem { match elem {
ProjectionElem::Deref => { ProjectionElem::Deref => match base_access {
match base_access { StorageDeadOrDrop::LocalStorageDead
StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => {
| StorageDeadOrDrop::BoxedStorageDead => { assert!(
assert!(base.ty(self.mir, tcx).to_ty(tcx).is_box(), base.ty(self.mir, tcx).to_ty(tcx).is_box(),
"Drop of value behind a reference or raw pointer"); "Drop of value behind a reference or raw pointer"
StorageDeadOrDrop::BoxedStorageDead );
} StorageDeadOrDrop::BoxedStorageDead
StorageDeadOrDrop::Destructor(_) => {
base_access
}
} }
} StorageDeadOrDrop::Destructor(_) => base_access,
ProjectionElem::Field(..) },
| ProjectionElem::Downcast(..) => { ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
let base_ty = base.ty(self.mir, tcx).to_ty(tcx); let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
match base_ty.sty { match base_ty.sty {
ty::Adt(def, _) if def.has_dtor(tcx) => { ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor // Report the outermost adt with a destructor
match base_access { match base_access {
StorageDeadOrDrop::Destructor(_) => { StorageDeadOrDrop::Destructor(_) => base_access,
base_access
}
StorageDeadOrDrop::LocalStorageDead StorageDeadOrDrop::LocalStorageDead
| StorageDeadOrDrop::BoxedStorageDead => { | StorageDeadOrDrop::BoxedStorageDead => {
StorageDeadOrDrop::Destructor(base_ty) StorageDeadOrDrop::Destructor(base_ty)
@ -1277,13 +1299,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
if is_closure { if is_closure {
None None
} else { } else {
let ty = self.infcx.tcx.type_of(self.mir_def_id); let ty = self.infcx.tcx.type_of(self.mir_def_id);
match ty.sty { match ty.sty {
ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => self.annotate_fn_sig(
self.annotate_fn_sig( self.mir_def_id,
self.mir_def_id, self.infcx.tcx.fn_sig(self.mir_def_id),
self.infcx.tcx.fn_sig(self.mir_def_id) ),
),
_ => None, _ => None,
} }
} }
@ -1296,13 +1317,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// place. If it was, we can add annotations about the function's return type and arguments // place. If it was, we can add annotations about the function's return type and arguments
// and it'll make sense. // and it'll make sense.
let location = borrow.reserve_location; let location = borrow.reserve_location;
debug!("annotate_argument_and_return_for_borrow: location={:?}", location); debug!(
match &self.mir[location.block].statements.get(location.statement_index) { "annotate_argument_and_return_for_borrow: location={:?}",
location
);
match &self.mir[location.block]
.statements
.get(location.statement_index)
{
Some(&Statement { Some(&Statement {
kind: StatementKind::Assign(ref reservation, _), kind: StatementKind::Assign(ref reservation, _),
.. ..
}) => { }) => {
debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation); debug!(
"annotate_argument_and_return_for_borrow: reservation={:?}",
reservation
);
// Check that the initial assignment of the reserve location is into a temporary. // Check that the initial assignment of the reserve location is into a temporary.
let mut target = *match reservation { let mut target = *match reservation {
Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local, Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
@ -1317,21 +1347,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
target, stmt target, stmt
); );
if let StatementKind::Assign( if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
Place::Local(assigned_to), {
box rvalue, debug!(
) = &stmt.kind { "annotate_argument_and_return_for_borrow: assigned_to={:?} \
debug!("annotate_argument_and_return_for_borrow: assigned_to={:?} \ rvalue={:?}",
rvalue={:?}", assigned_to, rvalue); assigned_to, rvalue
);
// Check if our `target` was captured by a closure. // Check if our `target` was captured by a closure.
if let Rvalue::Aggregate( if let Rvalue::Aggregate(
box AggregateKind::Closure(def_id, substs), box AggregateKind::Closure(def_id, substs),
operands, operands,
) = rvalue { ) = rvalue
{
for operand in operands { for operand in operands {
let assigned_from = match operand { let assigned_from = match operand {
Operand::Copy(assigned_from) | Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
Operand::Move(assigned_from) => assigned_from, assigned_from
}
_ => continue, _ => continue,
}; };
debug!( debug!(
@ -1354,13 +1387,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// case it ends up being assigned into the return place. // case it ends up being assigned into the return place.
annotated_closure = self.annotate_fn_sig( annotated_closure = self.annotate_fn_sig(
*def_id, *def_id,
self.infcx.closure_sig(*def_id, *substs) self.infcx.closure_sig(*def_id, *substs),
); );
debug!( debug!(
"annotate_argument_and_return_for_borrow: \ "annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \ annotated_closure={:?} assigned_from_local={:?} \
assigned_to={:?}", assigned_to={:?}",
annotated_closure, assigned_from_local, assigned_to annotated_closure, assigned_from_local, assigned_to
); );
if *assigned_to == mir::RETURN_PLACE { if *assigned_to == mir::RETURN_PLACE {
@ -1382,15 +1415,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let assigned_from = match rvalue { let assigned_from = match rvalue {
Rvalue::Ref(_, _, assigned_from) => assigned_from, Rvalue::Ref(_, _, assigned_from) => assigned_from,
Rvalue::Use(operand) => match operand { Rvalue::Use(operand) => match operand {
Operand::Copy(assigned_from) | Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
Operand::Move(assigned_from) => assigned_from, assigned_from
}
_ => continue, _ => continue,
}, },
_ => continue, _ => continue,
}; };
debug!( debug!(
"annotate_argument_and_return_for_borrow: \ "annotate_argument_and_return_for_borrow: \
assigned_from={:?}", assigned_from, assigned_from={:?}",
assigned_from,
); );
// Find the local from the rvalue. // Find the local from the rvalue.
@ -1400,7 +1435,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}; };
debug!( debug!(
"annotate_argument_and_return_for_borrow: \ "annotate_argument_and_return_for_borrow: \
assigned_from_local={:?}", assigned_from_local, assigned_from_local={:?}",
assigned_from_local,
); );
// Check if our local matches the target - if so, we've assigned our // Check if our local matches the target - if so, we've assigned our
@ -1414,7 +1450,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
debug!( debug!(
"annotate_argument_and_return_for_borrow: \ "annotate_argument_and_return_for_borrow: \
assigned_from_local={:?} assigned_to={:?}", assigned_from_local={:?} assigned_to={:?}",
assigned_from_local, assigned_to assigned_from_local, assigned_to
); );
if *assigned_to == mir::RETURN_PLACE { if *assigned_to == mir::RETURN_PLACE {
// If it was then return the annotated closure if there was one, // If it was then return the annotated closure if there was one,
@ -1438,15 +1474,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
destination: Some((Place::Local(assigned_to), _)), destination: Some((Place::Local(assigned_to), _)),
args, args,
.. ..
} = &terminator.kind { } = &terminator.kind
{
debug!( debug!(
"annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
assigned_to, args assigned_to, args
); );
for operand in args { for operand in args {
let assigned_from = match operand { let assigned_from = match operand {
Operand::Copy(assigned_from) | Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
Operand::Move(assigned_from) => assigned_from, assigned_from
}
_ => continue, _ => continue,
}; };
debug!( debug!(
@ -1460,9 +1498,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
assigned_from_local, assigned_from_local,
); );
if *assigned_to == mir::RETURN_PLACE && if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
assigned_from_local == target
{
return annotated_closure.or_else(fallback); return annotated_closure.or_else(fallback);
} }
} }
@ -1529,7 +1565,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// With access to the lifetime, we can get // With access to the lifetime, we can get
// the span of it. // the span of it.
arguments.push((*argument, lifetime.span)); arguments.push((*argument, lifetime.span));
}, }
_ => bug!("ty type is a ref but hir type is not"), _ => bug!("ty type is a ref but hir type is not"),
} }
} }
@ -1556,7 +1592,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
return_ty, return_ty,
return_span, return_span,
}) })
}, }
ty::TyKind::Ref(_, _, _) if is_closure => { ty::TyKind::Ref(_, _, _) if is_closure => {
// This is case 2 from above but only for closures, return type is anonymous // This is case 2 from above but only for closures, return type is anonymous
// reference so we select // reference so we select
@ -1577,7 +1613,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} }
None None
}, }
ty::TyKind::Ref(_, _, _) => { ty::TyKind::Ref(_, _, _) => {
// This is also case 2 from above but for functions, return type is still an // This is also case 2 from above but for functions, return type is still an
// anonymous reference so we select the first argument. // anonymous reference so we select the first argument.
@ -1589,7 +1625,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// We expect the first argument to be a reference. // We expect the first argument to be a reference.
match argument_ty.sty { match argument_ty.sty {
ty::TyKind::Ref(_, _, _) => {}, ty::TyKind::Ref(_, _, _) => {}
_ => return None, _ => return None,
} }
@ -1599,12 +1635,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
return_ty, return_ty,
return_span, return_span,
}) })
}, }
_ => { _ => {
// This is case 3 from above, return type is not a reference so don't highlight // This is case 3 from above, return type is not a reference so don't highlight
// anything. // anything.
None None
}, }
} }
} }
} }
@ -1625,25 +1661,25 @@ enum AnnotatedBorrowFnSignature<'tcx> {
Closure { Closure {
argument_ty: ty::Ty<'tcx>, argument_ty: ty::Ty<'tcx>,
argument_span: Span, argument_span: Span,
} },
} }
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
/// Annotate the provided diagnostic with information about borrow from the fn signature that /// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain. /// helps explain.
fn emit( fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
&self,
diag: &mut DiagnosticBuilder<'_>
) -> String {
match self { match self {
AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => { AnnotatedBorrowFnSignature::Closure {
argument_ty,
argument_span,
} => {
diag.span_label( diag.span_label(
*argument_span, *argument_span,
format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)), format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)),
); );
self.get_region_name_for_ty(argument_ty, 0) self.get_region_name_for_ty(argument_ty, 0)
}, }
AnnotatedBorrowFnSignature::AnonymousFunction { AnnotatedBorrowFnSignature::AnonymousFunction {
argument_ty, argument_ty,
argument_span, argument_span,
@ -1651,10 +1687,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
return_span, return_span,
} => { } => {
let argument_ty_name = self.get_name_for_ty(argument_ty, 0); let argument_ty_name = self.get_name_for_ty(argument_ty, 0);
diag.span_label( diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name));
*argument_span,
format!("has type `{}`", argument_ty_name)
);
let return_ty_name = self.get_name_for_ty(return_ty, 0); let return_ty_name = self.get_name_for_ty(return_ty, 0);
let types_equal = return_ty_name == argument_ty_name; let types_equal = return_ty_name == argument_ty_name;
@ -1664,7 +1697,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
"{}has type `{}`", "{}has type `{}`",
if types_equal { "also " } else { "" }, if types_equal { "also " } else { "" },
return_ty_name, return_ty_name,
) ),
); );
diag.note( diag.note(
@ -1676,7 +1709,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
); );
self.get_region_name_for_ty(return_ty, 0) self.get_region_name_for_ty(return_ty, 0)
}, }
AnnotatedBorrowFnSignature::NamedFunction { AnnotatedBorrowFnSignature::NamedFunction {
arguments, arguments,
return_ty, return_ty,
@ -1685,30 +1718,22 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
// Region of return type and arguments checked to be the same earlier. // Region of return type and arguments checked to be the same earlier.
let region_name = self.get_region_name_for_ty(return_ty, 0); let region_name = self.get_region_name_for_ty(return_ty, 0);
for (_, argument_span) in arguments { for (_, argument_span) in arguments {
diag.span_label( diag.span_label(*argument_span, format!("has lifetime `{}`", region_name));
*argument_span,
format!("has lifetime `{}`", region_name)
);
} }
diag.span_label( diag.span_label(
*return_span, *return_span,
format!( format!("also has lifetime `{}`", region_name,),
"also has lifetime `{}`",
region_name,
)
); );
diag.help( diag.help(&format!(
&format!( "use data from the highlighted arguments which match the `{}` lifetime of \
"use data from the highlighted arguments which match the `{}` lifetime of \ the return type",
the return type", region_name,
region_name, ));
),
);
region_name region_name
}, }
} }
} }
@ -1719,9 +1744,10 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
// this by hooking into the pretty printer and telling it to label the // this by hooking into the pretty printer and telling it to label the
// lifetimes without names with the value `'0`. // lifetimes without names with the value `'0`.
match ty.sty { match ty.sty {
ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _) | ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
ty::TyKind::Ref(ty::RegionKind::ReSkolemized(_, br), _, _) => | ty::TyKind::Ref(ty::RegionKind::ReSkolemized(_, br), _, _) => {
with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)), with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty))
}
_ => format!("{}", ty), _ => format!("{}", ty),
} }
} }
@ -1731,11 +1757,11 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
match ty.sty { match ty.sty {
ty::TyKind::Ref(region, _, _) => match region { ty::TyKind::Ref(region, _, _) => match region {
ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::ReSkolemized(_, br) => {
ty::RegionKind::ReSkolemized(_, br) => with_highlight_region_for_bound_region(*br, counter, || format!("{}", region))
with_highlight_region_for_bound_region(*br, counter, || format!("{}", region)), }
_ => format!("{}", region), _ => format!("{}", region),
} },
_ => bug!("ty for annotation of borrow region is not a reference"), _ => bug!("ty for annotation of borrow region is not a reference"),
} }
} }
@ -1828,9 +1854,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
debug!("find_closure_move_span: found closure {:?}", places); debug!("find_closure_move_span: found closure {:?}", places);
if let Some(node_id) = self.infcx.tcx.hir.as_local_node_id(def_id) { if let Some(node_id) = self.infcx.tcx.hir.as_local_node_id(def_id) {
if let Closure( if let Closure(_, _, _, args_span, _) =
_, _, _, args_span, _ self.infcx.tcx.hir.expect_expr(node_id).node
) = self.infcx.tcx.hir.expect_expr(node_id).node { {
if let Some(var_span) = self.infcx.tcx.with_freevars(node_id, |freevars| { if let Some(var_span) = self.infcx.tcx.with_freevars(node_id, |freevars| {
for (v, place) in freevars.iter().zip(places) { for (v, place) in freevars.iter().zip(places) {
match place { match place {
@ -1886,8 +1912,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} }
for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
if let StatementKind::Assign(_, box Rvalue::Aggregate(ref kind, ref places)) if let StatementKind::Assign(_, box Rvalue::Aggregate(ref kind, ref places)) = stmt.kind
= stmt.kind { {
if let AggregateKind::Closure(def_id, _) = **kind { if let AggregateKind::Closure(def_id, _) = **kind {
debug!("find_closure_borrow_span: found closure {:?}", places); debug!("find_closure_borrow_span: found closure {:?}", places);
@ -1900,13 +1926,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
return OtherUse(use_span); return OtherUse(use_span);
}; };
self.infcx.tcx self.infcx
.tcx
.with_freevars(node_id, |freevars| { .with_freevars(node_id, |freevars| {
for (v, place) in freevars.iter().zip(places) { for (v, place) in freevars.iter().zip(places) {
match *place { match *place {
Operand::Copy(Place::Local(l)) Operand::Copy(Place::Local(l))
| Operand::Move(Place::Local(l)) | Operand::Move(Place::Local(l)) if local == l =>
if local == l =>
{ {
debug!( debug!(
"find_closure_borrow_span: found captured local \ "find_closure_borrow_span: found captured local \
@ -1919,10 +1945,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} }
} }
None None
}).map(|var_span| ClosureUse { })
.map(|var_span| ClosureUse {
args_span, args_span,
var_span, var_span,
}).unwrap_or(OtherUse(use_span)) })
.unwrap_or(OtherUse(use_span))
} else { } else {
OtherUse(use_span) OtherUse(use_span)
}; };