diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a4e9e9579950b..22b135bee492a 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; @@ -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, @@ -45,22 +56,30 @@ 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(); - 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.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 +96,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, ); @@ -91,10 +109,15 @@ 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 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={:?}", + move_out_indices + ); return; } } @@ -110,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); @@ -126,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"); @@ -166,13 +197,14 @@ 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) { - 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 +218,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(move_out_indices, (place.clone(), err)) + { // Cancel the old error so it doesn't ICE. old_err.cancel(); } @@ -255,8 +286,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 +329,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 +341,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 +353,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 +377,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 +395,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 +405,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 +418,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 +479,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 +500,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 +513,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 +522,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 +584,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 +592,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 +608,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 +649,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 +659,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 +702,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 +732,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); @@ -715,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 @@ -756,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 @@ -785,16 +835,25 @@ 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, + location, + |m| { + if m == mpi { + any_match = true; + } + }, + ); if any_match { 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 @@ -829,7 +888,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 +1211,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 +1280,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 +1334,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 +1352,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 +1382,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 +1422,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 +1450,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 +1470,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 +1485,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 +1509,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 +1533,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 +1600,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 +1627,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 +1648,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 +1660,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 +1670,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 +1696,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 +1722,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 +1732,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { "{}has type `{}`", if types_equal { "also " } else { "" }, return_ty_name, - ) + ), ); diag.note( @@ -1676,7 +1744,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ); self.get_region_name_for_ty(return_ty, 0) - }, + } AnnotatedBorrowFnSignature::NamedFunction { arguments, return_ty, @@ -1685,30 +1753,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 +1779,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 +1792,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 +1889,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 +1947,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 +1961,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 +1980,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) }; 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); }, 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-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/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/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`. 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