From 2ac6cdf6a187d5491af7da36b786b2bbd2fd6e39 Mon Sep 17 00:00:00 2001 From: Rusty Blitzerr Date: Thu, 27 Sep 2018 19:10:29 -0700 Subject: [PATCH 1/4] Ran RustFmt on the file --- .../borrow_check/error_reporting.rs | 440 ++++++++++-------- 1 file changed, 234 insertions(+), 206 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a4e9e9579950b..a62051121a354 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -8,22 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::WriteKind; -use borrow_check::prefixes::IsPrefixOf; 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::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, FakeReadCause, Field, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm, }; -use rustc::hir; -use rustc::hir::def_id::DefId; use rustc::ty; +use rustc::util::ppaux::with_highlight_region_for_bound_region; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc::util::ppaux::with_highlight_region_for_bound_region; use syntax_pos::Span; use super::borrow_set::BorrowData; @@ -45,12 +45,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) { debug!( "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \ - span={:?} mpi={:?}", + span={:?} mpi={:?}", context, desired_action, place, span, mpi ); - let use_spans = self - .move_spans(place, context.loc) + let use_spans = self.move_spans(place, context.loc) .or_else(|| self.borrow_spans(span, context.loc)); let span = use_spans.args_or_use(); @@ -60,7 +59,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if mois.is_empty() { 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!( "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", 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( span, desired_action.as_noun(), - &self - .describe_place_with_options(place, IncludingDowncast(true)) + &self.describe_place_with_options(place, IncludingDowncast(true)) .unwrap_or("_".to_owned()), Origin::Mir, ); @@ -92,9 +92,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.buffer(&mut self.errors_buffer); } else { if let Some((reported_place, _)) = self.move_error_reported.get(&mois) { - if self.prefixes(&reported_place, PrefixSet::All).any(|p| p == place) { - debug!("report_use_of_moved_or_uninitialized place: error suppressed \ - mois={:?}", mois); + if self.prefixes(&reported_place, PrefixSet::All) + .any(|p| p == place) + { + debug!( + "report_use_of_moved_or_uninitialized place: error suppressed \ + mois={:?}", + mois + ); return; } } @@ -170,9 +175,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; if let Some(ty) = self.retrieve_type_for_place(place) { - let note_msg = match self - .describe_place_with_options(place, IncludingDowncast(true)) - { + let note_msg = match self.describe_place_with_options( + place, + IncludingDowncast(true), + ) { Some(name) => format!("`{}`", name), 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( - mois, - (place.clone(), err) - ) { + if let Some((_, mut old_err)) = + self.move_error_reported.insert(mois, (place.clone(), err)) + { // Cancel the old error so it doesn't ICE. old_err.cancel(); } @@ -255,8 +260,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, &self.describe_place(place).unwrap_or("_".to_owned()), borrow_span, - &self - .describe_place(&borrow.borrowed_place) + &self.describe_place(&borrow.borrowed_place) .unwrap_or("_".to_owned()), Origin::Mir, ); @@ -299,8 +303,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "mutable", ) { (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) - | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => tcx - .cannot_reborrow_already_borrowed( + | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => { + tcx.cannot_reborrow_already_borrowed( span, &desc_place, "", @@ -311,10 +315,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ), + ) + } - (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => tcx - .cannot_mutably_borrow_multiply( + (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => { + tcx.cannot_mutably_borrow_multiply( span, &desc_place, "", @@ -322,16 +327,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ), + ) + } - (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => tcx - .cannot_uniquely_borrow_by_two_closures( + (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => { + tcx.cannot_uniquely_borrow_by_two_closures( span, &desc_place, issued_span, None, Origin::Mir, - ), + ) + } (BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _) | (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => { @@ -344,10 +351,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); borrow_spans.var_span_label( &mut err, - format!( - "borrow occurs due to use of `{}` in closure", - desc_place - ), + format!("borrow occurs due to use of `{}` in closure", desc_place), ); err.buffer(&mut self.errors_buffer); @@ -365,8 +369,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Origin::Mir, ), - (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => tcx - .cannot_reborrow_already_uniquely_borrowed( + (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => { + tcx.cannot_reborrow_already_uniquely_borrowed( span, &desc_place, "", @@ -375,10 +379,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ), + ) + } - (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => tcx - .cannot_reborrow_already_uniquely_borrowed( + (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => { + tcx.cannot_reborrow_already_uniquely_borrowed( span, &desc_place, "", @@ -387,13 +392,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ), + ) + } (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _) | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => { // Shallow borrows are uses from the user's point of view. self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow); - return + return; } (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) | (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _) @@ -447,16 +453,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place_span: (&Place<'tcx>, Span), kind: Option, ) { - debug!("report_borrowed_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}\ - )", - context, borrow, place_span, kind + debug!( + "report_borrowed_value_does_not_live_long_enough(\ + {:?}, {:?}, {:?}, {:?}\ + )", + context, borrow, place_span, kind ); let drop_span = place_span.1; let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id); - let root_place = self - .prefixes(&borrow.borrowed_place, PrefixSet::All) + let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) .last() .unwrap(); @@ -468,8 +474,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => drop_span, }; - if self - .access_place_error_reported + if self.access_place_error_reported .contains(&(root_place.clone(), borrow_span)) { debug!( @@ -482,8 +487,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.access_place_error_reported .insert((root_place.clone(), borrow_span)); - if let StorageDeadOrDrop::Destructor(dropped_ty) - = self.classify_drop_access_kind(&borrow.borrowed_place) + if let StorageDeadOrDrop::Destructor(dropped_ty) = + self.classify_drop_access_kind(&borrow.borrowed_place) { // If a borrow of path `B` conflicts with drop of `D` (and // 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. if !borrow.borrowed_place.is_prefix_of(place_span.0) { self.report_borrow_conflicts_with_destructor( - context, - borrow, - place_span, - kind, - dropped_ty, + context, borrow, place_span, kind, dropped_ty, ); return; } } let err = match &self.describe_place(&borrow.borrowed_place) { - Some(_) if self.is_place_thread_local(root_place) => - self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span), + Some(_) if self.is_place_thread_local(root_place) => { + 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( context, name, @@ -556,7 +558,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label( 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) { @@ -564,8 +566,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, format!( "...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( @@ -579,16 +582,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } else { err.span_label( 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); } } else { 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"); @@ -616,7 +623,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let borrow_spans = self.retrieve_borrow_spans(borrow); 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) { 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) { - Some(borrowed) => - format!("here, drop of {D} needs exclusive access to `{B}`, \ - because the type `{T}` implements the `Drop` trait", - D=what_was_dropped, T=dropped_ty, B=borrowed), - None => - format!("here is drop of {D}; whose type `{T}` implements the `Drop` trait", - D=what_was_dropped, T=dropped_ty), + Some(borrowed) => format!( + "here, drop of {D} needs exclusive access to `{B}`, \ + because the type `{T}` implements the `Drop` trait", + D = what_was_dropped, + T = dropped_ty, + B = borrowed + ), + 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); // 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)), - ); + let explanation = + self.explain_why_borrow_contains_point(context, borrow, kind.map(|k| (k, place))); match explanation { - BorrowExplanation::UsedLater {..} | - BorrowExplanation::UsedLaterWhenDropped {..} => { + BorrowExplanation::UsedLater { .. } + | BorrowExplanation::UsedLaterWhenDropped { .. } => { err.note("consider using a `let` binding to create a longer lived value"); - }, - _ => {}, + } + _ => {} } explanation.emit(self.infcx.tcx, &mut err); @@ -663,9 +676,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span ); - let mut err = self.infcx.tcx.thread_local_value_does_not_live_long_enough( - borrow_span, Origin::Mir - ); + let mut err = self.infcx + .tcx + .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir); err.span_label( borrow_span, @@ -693,20 +706,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); let tcx = self.infcx.tcx; - let mut err = - tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir); - err.span_label(proper_span, "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 mut err = tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir); + err.span_label( + proper_span, + "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); match explanation { - BorrowExplanation::UsedLater(..) | - BorrowExplanation::UsedLaterInLoop(..) | - BorrowExplanation::UsedLaterWhenDropped(..) => { + BorrowExplanation::UsedLater(..) + | BorrowExplanation::UsedLaterInLoop(..) + | BorrowExplanation::UsedLaterWhenDropped(..) => { // Only give this note and suggestion if it could be relevant. err.note("consider using a `let` binding to create a longer lived value"); - }, - _ => {}, + } + _ => {} } explanation.emit(self.infcx.tcx, &mut err); @@ -785,11 +803,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // check for inits let mut any_match = false; - drop_flag_effects::for_location_inits(self.infcx.tcx, self.mir, self.move_data, l, |m| { - if m == mpi { - any_match = true; - } - }); + drop_flag_effects::for_location_inits( + self.infcx.tcx, + self.mir, + self.move_data, + l, + |m| { + if m == mpi { + any_match = true; + } + }, + ); if any_match { 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"); - 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); } @@ -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 // be borrowck'ing it, so we can just 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() } @@ -1218,35 +1245,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> { let tcx = self.infcx.tcx; match place { - Place::Local(_) - | Place::Static(_) - | Place::Promoted(_) => StorageDeadOrDrop::LocalStorageDead, + Place::Local(_) | Place::Static(_) | Place::Promoted(_) => { + StorageDeadOrDrop::LocalStorageDead + } Place::Projection(box PlaceProjection { base, elem }) => { let base_access = self.classify_drop_access_kind(base); match elem { - ProjectionElem::Deref => { - match base_access { - StorageDeadOrDrop::LocalStorageDead - | StorageDeadOrDrop::BoxedStorageDead => { - assert!(base.ty(self.mir, tcx).to_ty(tcx).is_box(), - "Drop of value behind a reference or raw pointer"); - StorageDeadOrDrop::BoxedStorageDead - } - StorageDeadOrDrop::Destructor(_) => { - base_access - } + ProjectionElem::Deref => match base_access { + StorageDeadOrDrop::LocalStorageDead + | StorageDeadOrDrop::BoxedStorageDead => { + assert!( + base.ty(self.mir, tcx).to_ty(tcx).is_box(), + "Drop of value behind a reference or raw pointer" + ); + StorageDeadOrDrop::BoxedStorageDead } - } - ProjectionElem::Field(..) - | ProjectionElem::Downcast(..) => { + StorageDeadOrDrop::Destructor(_) => base_access, + }, + ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { let base_ty = base.ty(self.mir, tcx).to_ty(tcx); match base_ty.sty { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor match base_access { - StorageDeadOrDrop::Destructor(_) => { - base_access - } + StorageDeadOrDrop::Destructor(_) => base_access, StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { StorageDeadOrDrop::Destructor(base_ty) @@ -1277,13 +1299,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if is_closure { None } else { - let ty = self.infcx.tcx.type_of(self.mir_def_id); - match ty.sty { - ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => - self.annotate_fn_sig( - self.mir_def_id, - self.infcx.tcx.fn_sig(self.mir_def_id) - ), + let ty = self.infcx.tcx.type_of(self.mir_def_id); + match ty.sty { + ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => self.annotate_fn_sig( + self.mir_def_id, + self.infcx.tcx.fn_sig(self.mir_def_id), + ), _ => 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 // and it'll make sense. let location = borrow.reserve_location; - debug!("annotate_argument_and_return_for_borrow: location={:?}", location); - match &self.mir[location.block].statements.get(location.statement_index) { + debug!( + "annotate_argument_and_return_for_borrow: location={:?}", + location + ); + match &self.mir[location.block] + .statements + .get(location.statement_index) + { Some(&Statement { 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. let mut target = *match reservation { 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={:?}", target, stmt ); - if let StatementKind::Assign( - Place::Local(assigned_to), - box rvalue, - ) = &stmt.kind { - debug!("annotate_argument_and_return_for_borrow: assigned_to={:?} \ - rvalue={:?}", assigned_to, rvalue); + if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind + { + debug!( + "annotate_argument_and_return_for_borrow: assigned_to={:?} \ + rvalue={:?}", + assigned_to, rvalue + ); // Check if our `target` was captured by a closure. if let Rvalue::Aggregate( - box AggregateKind::Closure(def_id, substs), - operands, - ) = rvalue { + box AggregateKind::Closure(def_id, substs), + operands, + ) = rvalue + { for operand in operands { let assigned_from = match operand { - Operand::Copy(assigned_from) | - Operand::Move(assigned_from) => assigned_from, + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } _ => continue, }; debug!( @@ -1354,13 +1387,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // case it ends up being assigned into the return place. annotated_closure = self.annotate_fn_sig( *def_id, - self.infcx.closure_sig(*def_id, *substs) + self.infcx.closure_sig(*def_id, *substs), ); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ assigned_to={:?}", - annotated_closure, assigned_from_local, assigned_to + annotated_closure, assigned_from_local, assigned_to ); if *assigned_to == mir::RETURN_PLACE { @@ -1382,15 +1415,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let assigned_from = match rvalue { Rvalue::Ref(_, _, assigned_from) => assigned_from, Rvalue::Use(operand) => match operand { - Operand::Copy(assigned_from) | - Operand::Move(assigned_from) => assigned_from, + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } _ => continue, }, _ => continue, }; debug!( "annotate_argument_and_return_for_borrow: \ - assigned_from={:?}", assigned_from, + assigned_from={:?}", + assigned_from, ); // Find the local from the rvalue. @@ -1400,7 +1435,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }; debug!( "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 @@ -1414,7 +1450,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { debug!( "annotate_argument_and_return_for_borrow: \ assigned_from_local={:?} assigned_to={:?}", - assigned_from_local, assigned_to + assigned_from_local, assigned_to ); if *assigned_to == mir::RETURN_PLACE { // 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), _)), args, .. - } = &terminator.kind { + } = &terminator.kind + { debug!( "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", assigned_to, args ); for operand in args { let assigned_from = match operand { - Operand::Copy(assigned_from) | - Operand::Move(assigned_from) => assigned_from, + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } _ => continue, }; debug!( @@ -1460,9 +1498,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { assigned_from_local, ); - if *assigned_to == mir::RETURN_PLACE && - assigned_from_local == target - { + if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target { 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 // the span of it. arguments.push((*argument, lifetime.span)); - }, + } _ => 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_span, }) - }, + } ty::TyKind::Ref(_, _, _) if is_closure => { // This is case 2 from above but only for closures, return type is anonymous // reference so we select @@ -1577,7 +1613,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } None - }, + } ty::TyKind::Ref(_, _, _) => { // This is also case 2 from above but for functions, return type is still an // 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. match argument_ty.sty { - ty::TyKind::Ref(_, _, _) => {}, + ty::TyKind::Ref(_, _, _) => {} _ => return None, } @@ -1599,12 +1635,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return_ty, return_span, }) - }, + } _ => { // This is case 3 from above, return type is not a reference so don't highlight // anything. None - }, + } } } } @@ -1625,25 +1661,25 @@ enum AnnotatedBorrowFnSignature<'tcx> { Closure { argument_ty: ty::Ty<'tcx>, argument_span: Span, - } + }, } impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - fn emit( - &self, - diag: &mut DiagnosticBuilder<'_> - ) -> String { + fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String { match self { - AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => { + AnnotatedBorrowFnSignature::Closure { + argument_ty, + argument_span, + } => { diag.span_label( *argument_span, format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)), ); self.get_region_name_for_ty(argument_ty, 0) - }, + } AnnotatedBorrowFnSignature::AnonymousFunction { argument_ty, argument_span, @@ -1651,10 +1687,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { return_span, } => { let argument_ty_name = self.get_name_for_ty(argument_ty, 0); - diag.span_label( - *argument_span, - format!("has type `{}`", argument_ty_name) - ); + diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name)); let return_ty_name = self.get_name_for_ty(return_ty, 0); let types_equal = return_ty_name == argument_ty_name; @@ -1664,7 +1697,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { "{}has type `{}`", if types_equal { "also " } else { "" }, return_ty_name, - ) + ), ); diag.note( @@ -1676,7 +1709,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ); self.get_region_name_for_ty(return_ty, 0) - }, + } AnnotatedBorrowFnSignature::NamedFunction { arguments, return_ty, @@ -1685,30 +1718,22 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { // Region of return type and arguments checked to be the same earlier. let region_name = self.get_region_name_for_ty(return_ty, 0); for (_, argument_span) in arguments { - diag.span_label( - *argument_span, - format!("has lifetime `{}`", region_name) - ); + diag.span_label(*argument_span, format!("has lifetime `{}`", region_name)); } diag.span_label( *return_span, - format!( - "also has lifetime `{}`", - region_name, - ) + format!("also has lifetime `{}`", region_name,), ); - diag.help( - &format!( - "use data from the highlighted arguments which match the `{}` lifetime of \ - the return type", - region_name, - ), - ); + diag.help(&format!( + "use data from the highlighted arguments which match the `{}` lifetime of \ + the return type", + 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 // lifetimes without names with the value `'0`. match ty.sty { - ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _) | - ty::TyKind::Ref(ty::RegionKind::ReSkolemized(_, br), _, _) => - with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)), + ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _) + | ty::TyKind::Ref(ty::RegionKind::ReSkolemized(_, br), _, _) => { + with_highlight_region_for_bound_region(*br, counter, || 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 { match ty.sty { ty::TyKind::Ref(region, _, _) => match region { - ty::RegionKind::ReLateBound(_, br) | - ty::RegionKind::ReSkolemized(_, br) => - with_highlight_region_for_bound_region(*br, counter, || format!("{}", region)), + ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::ReSkolemized(_, br) => { + with_highlight_region_for_bound_region(*br, counter, || format!("{}", region)) + } _ => format!("{}", region), - } + }, _ => 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); if let Some(node_id) = self.infcx.tcx.hir.as_local_node_id(def_id) { - if let Closure( - _, _, _, args_span, _ - ) = self.infcx.tcx.hir.expect_expr(node_id).node { + if let Closure(_, _, _, args_span, _) = + self.infcx.tcx.hir.expect_expr(node_id).node + { if let Some(var_span) = self.infcx.tcx.with_freevars(node_id, |freevars| { for (v, place) in freevars.iter().zip(places) { 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..] { - if let StatementKind::Assign(_, box Rvalue::Aggregate(ref kind, ref places)) - = stmt.kind { + if let StatementKind::Assign(_, box Rvalue::Aggregate(ref kind, ref places)) = stmt.kind + { if let AggregateKind::Closure(def_id, _) = **kind { debug!("find_closure_borrow_span: found closure {:?}", places); @@ -1900,13 +1926,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return OtherUse(use_span); }; - self.infcx.tcx + self.infcx + .tcx .with_freevars(node_id, |freevars| { for (v, place) in freevars.iter().zip(places) { match *place { Operand::Copy(Place::Local(l)) - | Operand::Move(Place::Local(l)) - if local == l => + | Operand::Move(Place::Local(l)) if local == l => { debug!( "find_closure_borrow_span: found captured local \ @@ -1919,10 +1945,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } None - }).map(|var_span| ClosureUse { + }) + .map(|var_span| ClosureUse { args_span, var_span, - }).unwrap_or(OtherUse(use_span)) + }) + .unwrap_or(OtherUse(use_span)) } else { OtherUse(use_span) }; From d5ae6f7870ff937d69a20078bdbbc2093bde2279 Mon Sep 17 00:00:00 2001 From: Rusty Blitzerr Date: Thu, 27 Sep 2018 22:16:29 -0700 Subject: [PATCH 2/4] [54015] NLL:Improve move error loop detection Before this patch running the following command would generate the given output: $ rustc +stage1 src/test/ui/liveness/liveness-move-in-while.rs -Zborrowck=mir -Ztwo-phase-borrows error[E0382]: borrow of moved value: `y` --> src/main.rs:8:24 | 8 | println!("{}", y); //~ ERROR use of moved value: `y` | ^ value borrowed here after move 9 | while true { while true { while true { x = y; x.clone(); } } } | - value moved here | = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait We want to give the user more hint by telling them that the value was moved in the previous iteration of the loop. After this patch, the error message adds the phrase "in previous iteration of loop" and in totality looks like this: $ rustc +stage1 src/test/ui/liveness/liveness-move-in-while.rs -Zborrowck=mir -Ztwo-phase-borrows error[E0382]: borrow of moved value: `y` --> src/test/ui/liveness/liveness-move-in-while.rs:17:24 | 17 | println!("{}", y); //~ ERROR use of moved value: `y` | ^ value borrowed here after move 18 | while true { while true { while true { x = y; x.clone(); } } } | - value moved here, in previous iteration of loop | = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait --- .../borrow_check/error_reporting.rs | 81 +++++++++++++------ .../borrow_check/nll/explain_borrow/mod.rs | 4 +- 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a62051121a354..22b135bee492a 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -35,6 +35,17 @@ use dataflow::move_paths::indexes::MoveOutIndex; use dataflow::move_paths::MovePathIndex; use util::borrowck_errors::{BorrowckErrors, Origin}; +#[derive(Debug)] +struct MoveSite { + /// Index of the "move out" that we found. The `MoveData` can + /// then tell us where the move occurred. + moi: MoveOutIndex, + + /// True if we traversed a back edge while walking from the point + /// of error to the move site. + traversed_back_edge: bool +} + impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_of_moved_or_uninitialized( &mut self, @@ -53,10 +64,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .or_else(|| self.borrow_spans(span, context.loc)); let span = use_spans.args_or_use(); - let mois = self.get_moved_indexes(context, mpi); - debug!("report_use_of_moved_or_uninitialized: mois={:?}", mois); + let move_site_vec = self.get_moved_indexes(context, mpi); + debug!( + "report_use_of_moved_or_uninitialized: move_site_vec={:?}", + move_site_vec + ); + let move_out_indices: Vec<_> = move_site_vec + .iter() + .map(|move_site| move_site.moi) + .collect(); - if mois.is_empty() { + if move_out_indices.is_empty() { let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); if self.uninitialized_error_reported @@ -91,14 +109,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.buffer(&mut self.errors_buffer); } else { - if let Some((reported_place, _)) = self.move_error_reported.get(&mois) { + if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { if self.prefixes(&reported_place, PrefixSet::All) .any(|p| p == place) { debug!( "report_use_of_moved_or_uninitialized place: error suppressed \ mois={:?}", - mois + move_out_indices ); return; } @@ -115,8 +133,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); let mut is_loop_move = false; - for moi in &mois { - let move_out = self.move_data.moves[*moi]; + for move_site in &move_site_vec { + let move_out = self.move_data.moves[(*move_site).moi]; let moved_place = &self.move_data.move_paths[move_out.path].place; let move_spans = self.move_spans(moved_place, move_out.source); @@ -131,9 +149,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if span == move_span { err.span_label( span, - format!("value moved{} here in previous iteration of loop", move_msg), + format!("value moved{} here, in previous iteration of loop", move_msg), ); is_loop_move = true; + } else if move_site.traversed_back_edge { + err.span_label( + move_span, + format!( + "value moved{} here, in previous iteration of loop", + move_msg + ), + ); } else { err.span_label(move_span, format!("value moved{} here", move_msg)); move_spans.var_span_label(&mut err, "variable moved due to use in closure"); @@ -171,7 +197,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }; if needs_note { - let mpi = self.move_data.moves[mois[0]].path; + let mpi = self.move_data.moves[move_out_indices[0]].path; let place = &self.move_data.move_paths[mpi].place; if let Some(ty) = self.retrieve_type_for_place(place) { @@ -192,8 +218,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - if let Some((_, mut old_err)) = - self.move_error_reported.insert(mois, (place.clone(), err)) + if let Some((_, mut old_err)) = self.move_error_reported + .insert(move_out_indices, (place.clone(), err)) { // Cancel the old error so it doesn't ICE. old_err.cancel(); @@ -733,29 +759,32 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err } - fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec { + fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec { let mir = self.mir; let mut stack = Vec::new(); - stack.extend(mir.predecessor_locations(context.loc)); + stack.extend(mir.predecessor_locations(context.loc).map(|predecessor| { + let is_back_edge = context.loc.dominates(predecessor, &self.dominators); + (predecessor, is_back_edge) + })); let mut visited = FxHashSet(); let mut result = vec![]; - 'dfs: while let Some(l) = stack.pop() { + 'dfs: while let Some((location, is_back_edge)) = stack.pop() { debug!( - "report_use_of_moved_or_uninitialized: current_location={:?}", - l + "report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})", + location, is_back_edge ); - if !visited.insert(l) { + if !visited.insert(location) { continue; } // check for moves - let stmt_kind = mir[l.block] + let stmt_kind = mir[location.block] .statements - .get(l.statement_index) + .get(location.statement_index) .map(|s| &s.kind); if let Some(StatementKind::StorageDead(..)) = stmt_kind { // this analysis only tries to find moves explicitly @@ -774,11 +803,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let move_paths = &self.move_data.move_paths; mpis.extend(move_paths[mpi].parents(move_paths)); - for moi in &self.move_data.loc_map[l] { + for moi in &self.move_data.loc_map[location] { debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); if mpis.contains(&self.move_data.moves[*moi].path) { debug!("report_use_of_moved_or_uninitialized: found"); - result.push(*moi); + result.push(MoveSite { + moi: *moi, + traversed_back_edge: is_back_edge, + }); // Strictly speaking, we could continue our DFS here. There may be // other moves that can reach the point of error. But it is kind of @@ -807,7 +839,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.infcx.tcx, self.mir, self.move_data, - l, + location, |m| { if m == mpi { any_match = true; @@ -818,7 +850,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { continue 'dfs; } - stack.extend(mir.predecessor_locations(l)); + stack.extend(mir.predecessor_locations(location).map(|predecessor| { + let back_edge = location.dominates(predecessor, &self.dominators); + (predecessor, is_back_edge || back_edge) + })); } result diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index f4052f948013a..8d1caec2d72d3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -46,9 +46,9 @@ impl<'tcx> BorrowExplanation<'tcx> { }, BorrowExplanation::UsedLaterInLoop(is_in_closure, var_or_use_span) => { let message = if is_in_closure { - "borrow captured here by closure in later iteration of loop" + "borrow captured here by closure, in later iteration of loop" } else { - "borrow used here in later iteration of loop" + "borrow used here, in later iteration of loop" }; err.span_label(var_or_use_span, message); }, From 44b3674d8e85df58126ae005faa615be5f651c43 Mon Sep 17 00:00:00 2001 From: Rusty Blitzerr Date: Fri, 28 Sep 2018 09:21:10 -0700 Subject: [PATCH 3/4] Test fixes for the change of error message for issue #54015 --- .../ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr | 4 ++-- src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr | 4 ++-- .../borrowck-mut-borrow-linear-errors.ast.nll.stderr | 4 ++-- .../borrowck/borrowck-mut-borrow-linear-errors.mir.stderr | 4 ++-- src/test/ui/borrowck/issue-41962.stderr | 2 +- src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr | 2 +- src/test/ui/issues/issue-12041.nll.stderr | 2 +- .../ui/issues/issue-52126-assign-op-invariance.nll.stderr | 2 +- src/test/ui/liveness/liveness-move-in-while.nll.stderr | 2 +- src/test/ui/nll/closures-in-loops.stderr | 2 +- src/test/ui/nll/issue-53807.nll.stderr | 2 +- .../borrowck-issue-49631.nll.stderr | 2 +- .../ui/span/regions-escape-loop-via-variable.nll.stderr | 2 +- src/test/ui/span/regions-escape-loop-via-vec.nll.stderr | 8 ++++---- src/test/ui/vec/vec-mut-iter-borrow.nll.stderr | 2 +- 15 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr index c3f71d60072b9..b7803cbc804ae 100644 --- a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr +++ b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr @@ -5,7 +5,7 @@ LL | for &x in &vector { | ------- | | | immutable borrow occurs here - | borrow used here in later iteration of loop + | borrow used here, in later iteration of loop LL | let cap = vector.capacity(); LL | vector.extend(repeat(0)); //~ ERROR cannot borrow | ^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here @@ -17,7 +17,7 @@ LL | for &x in &vector { | ------- | | | immutable borrow occurs here - | borrow used here in later iteration of loop + | borrow used here, in later iteration of loop ... LL | vector[1] = 5; //~ ERROR cannot borrow | ^^^^^^ mutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr b/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr index c46e94866ab5a..81aa1e2c9602e 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr +++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr @@ -8,13 +8,13 @@ LL | borrow(&*v); //~ ERROR cannot borrow | ^^^ immutable borrow occurs here LL | } LL | *x = box 5; - | -- borrow used here in later iteration of loop + | -- borrow used here, in later iteration of loop error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable --> $DIR/borrowck-lend-flow-loop.rs:109:16 | LL | **x += 1; - | -------- borrow used here in later iteration of loop + | -------- borrow used here, in later iteration of loop LL | borrow(&*v); //~ ERROR cannot borrow | ^^^ immutable borrow occurs here LL | if cond2 { diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr index b3c86a56091d2..19ec9cf7ded60 100644 --- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr @@ -4,7 +4,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time LL | 1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] | ---- ^^^^^^ second mutable borrow occurs here | | - | borrow used here in later iteration of loop + | borrow used here, in later iteration of loop ... LL | _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499] | ------ first mutable borrow occurs here @@ -13,7 +13,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/borrowck-mut-borrow-linear-errors.rs:25:30 | LL | 1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] - | ---- borrow used here in later iteration of loop + | ---- borrow used here, in later iteration of loop LL | //[mir]~^ ERROR [E0499] LL | 2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] | ^^^^^^ second mutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr index b3c86a56091d2..19ec9cf7ded60 100644 --- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr +++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr @@ -4,7 +4,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time LL | 1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] | ---- ^^^^^^ second mutable borrow occurs here | | - | borrow used here in later iteration of loop + | borrow used here, in later iteration of loop ... LL | _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499] | ------ first mutable borrow occurs here @@ -13,7 +13,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/borrowck-mut-borrow-linear-errors.rs:25:30 | LL | 1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] - | ---- borrow used here in later iteration of loop + | ---- borrow used here, in later iteration of loop LL | //[mir]~^ ERROR [E0499] LL | 2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] | ^^^^^^ second mutable borrow occurs here diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 957ccfe45dd01..39efdb6ddb40d 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -20,7 +20,7 @@ error[E0382]: use of moved value (Mir) --> $DIR/issue-41962.rs:17:21 | LL | if let Some(thing) = maybe { - | ^^^^^ value moved here in previous iteration of loop + | ^^^^^ value moved here, in previous iteration of loop | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr index 02e5b44c17c4a..dd445c8c3a06b 100644 --- a/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr +++ b/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr @@ -17,7 +17,7 @@ LL | let inner_second = &mut inner_void; //~ ERROR cannot borrow | ^^^^^^^^^^^^^^^ second mutable borrow occurs here LL | inner_second.use_mut(); LL | inner_first.use_mut(); - | ----------- borrow used here in later iteration of loop + | ----------- borrow used here, in later iteration of loop error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-12041.nll.stderr b/src/test/ui/issues/issue-12041.nll.stderr index b880317a2a612..a0b90c7a34a7f 100644 --- a/src/test/ui/issues/issue-12041.nll.stderr +++ b/src/test/ui/issues/issue-12041.nll.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tx` --> $DIR/issue-12041.rs:18:22 | LL | let tx = tx; - | ^^ value moved here in previous iteration of loop + | ^^ value moved here, in previous iteration of loop | = note: move occurs because `tx` has type `std::sync::mpsc::Sender`, which does not implement the `Copy` trait diff --git a/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr b/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr index e3e389d11970a..b25b063f3b6fb 100644 --- a/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr +++ b/src/test/ui/issues/issue-52126-assign-op-invariance.nll.stderr @@ -5,7 +5,7 @@ LL | let v: Vec<&str> = line.split_whitespace().collect(); | ^^^^ borrowed value does not live long enough LL | //~^ ERROR `line` does not live long enough LL | println!("accumulator before add_assign {:?}", acc.map); - | ------- borrow used here in later iteration of loop + | ------- borrow used here, in later iteration of loop ... LL | } | - `line` dropped here while still borrowed diff --git a/src/test/ui/liveness/liveness-move-in-while.nll.stderr b/src/test/ui/liveness/liveness-move-in-while.nll.stderr index 9f1ffd91518b3..065e65702b412 100644 --- a/src/test/ui/liveness/liveness-move-in-while.nll.stderr +++ b/src/test/ui/liveness/liveness-move-in-while.nll.stderr @@ -4,7 +4,7 @@ error[E0382]: borrow of moved value: `y` LL | println!("{}", y); //~ ERROR use of moved value: `y` | ^ value borrowed here after move LL | while true { while true { while true { x = y; x.clone(); } } } - | - value moved here + | - value moved here, in previous iteration of loop | = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr index 9758a80362000..cd7fdbdb6ed1e 100644 --- a/src/test/ui/nll/closures-in-loops.stderr +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -4,7 +4,7 @@ error[E0382]: use of moved value: `x` LL | || x; //~ ERROR | ^^ - use occurs due to use in closure | | - | value moved into closure here in previous iteration of loop + | value moved into closure here, in previous iteration of loop | = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait diff --git a/src/test/ui/nll/issue-53807.nll.stderr b/src/test/ui/nll/issue-53807.nll.stderr index 0c019a4ec3cdc..056046aa43aba 100644 --- a/src/test/ui/nll/issue-53807.nll.stderr +++ b/src/test/ui/nll/issue-53807.nll.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value --> $DIR/issue-53807.rs:14:21 | LL | if let Some(thing) = maybe { - | ^^^^^ value moved here in previous iteration of loop + | ^^^^^ value moved here, in previous iteration of loop | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr index 606d678542269..626ffad5ba70f 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr @@ -7,7 +7,7 @@ LL | foo.mutate(); | ^^^^^^^^^^^^ mutable borrow occurs here LL | //~^ ERROR cannot borrow `foo` as mutable LL | println!("foo={:?}", *string); - | ------- borrow used here in later iteration of loop + | ------- borrow used here, in later iteration of loop error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr index 7aaec700d8985..a6d86f6797438 100644 --- a/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr +++ b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr @@ -2,7 +2,7 @@ error[E0597]: `x` does not live long enough --> $DIR/regions-escape-loop-via-variable.rs:21:13 | LL | let x = 1 + *p; - | -- borrow used here in later iteration of loop + | -- borrow used here, in later iteration of loop LL | p = &x; | ^^ borrowed value does not live long enough LL | } diff --git a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr index 2dc758428ef3a..2f23a444dccba 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr @@ -7,7 +7,7 @@ LL | while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed | ^ use of borrowed `x` LL | let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed LL | _y.push(&mut z); - | -- borrow used here in later iteration of loop + | -- borrow used here, in later iteration of loop error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/regions-escape-loop-via-vec.rs:16:21 @@ -18,7 +18,7 @@ LL | while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed LL | let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed | ^ use of borrowed `x` LL | _y.push(&mut z); - | -- borrow used here in later iteration of loop + | -- borrow used here, in later iteration of loop error[E0597]: `z` does not live long enough --> $DIR/regions-escape-loop-via-vec.rs:17:17 @@ -26,7 +26,7 @@ error[E0597]: `z` does not live long enough LL | _y.push(&mut z); | -- ^^^^^^ borrowed value does not live long enough | | - | borrow used here in later iteration of loop + | borrow used here, in later iteration of loop ... LL | } | - `z` dropped here while still borrowed @@ -38,7 +38,7 @@ LL | let mut _y = vec![&mut x]; | ------ borrow of `x` occurs here ... LL | _y.push(&mut z); - | -- borrow used here in later iteration of loop + | -- borrow used here, in later iteration of loop LL | //~^ ERROR `z` does not live long enough LL | x += 1; //~ ERROR cannot assign | ^^^^^^ use of borrowed `x` diff --git a/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr b/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr index fd7843f39bc1e..cff263231dde7 100644 --- a/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr +++ b/src/test/ui/vec/vec-mut-iter-borrow.nll.stderr @@ -5,7 +5,7 @@ LL | for x in &mut xs { | ------- | | | first mutable borrow occurs here - | borrow used here in later iteration of loop + | borrow used here, in later iteration of loop LL | xs.push(1) //~ ERROR cannot borrow `xs` | ^^ second mutable borrow occurs here From 671e77d60b075ff3a757e1c528e759ac95fc1e13 Mon Sep 17 00:00:00 2001 From: Rusty Blitzerr Date: Fri, 28 Sep 2018 18:24:17 -0700 Subject: [PATCH 4/4] test fix for #54015 --- .../ui/liveness/liveness-move-call-arg.nll.stderr | 11 +++++++++++ src/test/ui/liveness/liveness-move-in-loop.nll.stderr | 11 +++++++++++ src/test/ui/moves/move-in-guard-2.nll.stderr | 11 +++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/test/ui/liveness/liveness-move-call-arg.nll.stderr create mode 100644 src/test/ui/liveness/liveness-move-in-loop.nll.stderr create mode 100644 src/test/ui/moves/move-in-guard-2.nll.stderr diff --git a/src/test/ui/liveness/liveness-move-call-arg.nll.stderr b/src/test/ui/liveness/liveness-move-call-arg.nll.stderr new file mode 100644 index 0000000000000..40add8d51f19e --- /dev/null +++ b/src/test/ui/liveness/liveness-move-call-arg.nll.stderr @@ -0,0 +1,11 @@ +error[E0382]: use of moved value: `x` + --> $DIR/liveness-move-call-arg.rs:19:14 + | +LL | take(x); //~ ERROR use of moved value: `x` + | ^ value moved here, in previous iteration of loop + | + = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/liveness/liveness-move-in-loop.nll.stderr b/src/test/ui/liveness/liveness-move-in-loop.nll.stderr new file mode 100644 index 0000000000000..e2719256bdfe8 --- /dev/null +++ b/src/test/ui/liveness/liveness-move-in-loop.nll.stderr @@ -0,0 +1,11 @@ +error[E0382]: use of moved value: `y` + --> $DIR/liveness-move-in-loop.rs:21:25 + | +LL | x = y; //~ ERROR use of moved value + | ^ value moved here, in previous iteration of loop + | + = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/move-in-guard-2.nll.stderr b/src/test/ui/moves/move-in-guard-2.nll.stderr new file mode 100644 index 0000000000000..2a53a98c0f265 --- /dev/null +++ b/src/test/ui/moves/move-in-guard-2.nll.stderr @@ -0,0 +1,11 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-in-guard-2.rs:20:24 + | +LL | (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` + | ^ value moved here, in previous iteration of loop + | + = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`.