From 903851f785aaa01b5ae2e9648a2fd1256eea2ba5 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 1 Aug 2018 20:38:02 +0100 Subject: [PATCH 1/3] Highlight closure spans for borrow and initialization errors --- .../borrow_check/error_reporting.rs | 519 ++++++++++++------ src/librustc_mir/borrow_check/mod.rs | 2 +- .../borrow_check/mutability_errors.rs | 43 +- .../borrow_check/nll/explain_borrow/mod.rs | 28 +- src/librustc_mir/util/borrowck_errors.rs | 11 +- 5 files changed, 403 insertions(+), 200 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index e2ac7dde55854..aabed6686858f 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -10,13 +10,14 @@ use borrow_check::WriteKind; use rustc::middle::region::ScopeTree; +use rustc::mir::VarBindingForm; use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; -use rustc::mir::VarBindingForm; use rustc::ty; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; +use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; use super::borrow_set::BorrowData; @@ -30,12 +31,17 @@ use util::borrowck_errors::{BorrowckErrors, Origin}; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_of_moved_or_uninitialized( &mut self, - _context: Context, + context: Context, desired_action: InitializationRequiringAction, (place, span): (&Place<'tcx>, Span), mpi: MovePathIndex, curr_move_out: &FlowAtLocation>, ) { + 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.move_data.path_map[mpi] .iter() .filter(|moi| curr_move_out.contains(moi)) @@ -58,16 +64,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; - let mut err = self.tcx - .cannot_act_on_uninitialized_variable( - span, - desired_action.as_noun(), - &self - .describe_place_with_options(place, IncludingDowncast(true)) - .unwrap_or("_".to_owned()), - Origin::Mir, - ); + let mut err = self.tcx.cannot_act_on_uninitialized_variable( + span, + desired_action.as_noun(), + &self + .describe_place_with_options(place, IncludingDowncast(true)) + .unwrap_or("_".to_owned()), + Origin::Mir, + ); err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use in closure", desired_action.as_noun()), + ); + err.buffer(&mut self.errors_buffer); } else { let msg = ""; //FIXME: add "partially " or "collaterally " @@ -82,11 +93,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut is_loop_move = false; for moi in &mois { - let move_msg = ""; //FIXME: add " (into closure)" - let move_span = self - .mir - .source_info(self.move_data.moves[**moi].source) - .span; + let move_out = self.move_data.moves[**moi]; + let moved_place = &self.move_data.move_paths[move_out.path].place; + + let move_spans = self.move_spans(moved_place, move_out.source); + let move_span = move_spans.args_or_use(); + + let move_msg = if move_spans.for_closure() { + " into closure" + } else { + "" + }; + if span == move_span { err.span_label( span, @@ -95,8 +113,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { is_loop_move = true; } 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"); }; } + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use in closure", desired_action.as_noun()), + ); + if !is_loop_move { err.span_label( span, @@ -150,7 +175,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_move_out_while_borrowed( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + (place, _span): (&Place<'tcx>, Span), borrow: &BorrowData<'tcx>, ) { let tcx = self.tcx; @@ -162,16 +187,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + let move_spans = self.move_spans(place, context.loc); + let span = move_spans.args_or_use(); + let mut err = tcx.cannot_move_when_borrowed( span, &self.describe_place(place).unwrap_or("_".to_owned()), Origin::Mir, ); - err.span_label( - self.retrieve_borrow_span(borrow), - format!("borrow of {} occurs here", borrow_msg), - ); + err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); err.span_label(span, format!("move out of {} occurs here", value_msg)); + + borrow_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); + + move_spans.var_span_label(&mut err, "move occurs due to use in closure"); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.buffer(&mut self.errors_buffer); } @@ -179,92 +213,38 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_while_mutably_borrowed( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + (place, _span): (&Place<'tcx>, Span), borrow: &BorrowData<'tcx>, ) { let tcx = self.tcx; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + // Conflicting borrows are reported separately, so only check for move + // captures. + let use_spans = self.move_spans(place, context.loc); + let span = use_spans.var_or_use(); + let mut err = tcx.cannot_use_when_mutably_borrowed( span, &self.describe_place(place).unwrap_or("_".to_owned()), - self.retrieve_borrow_span(borrow), + borrow_span, &self .describe_place(&borrow.borrowed_place) .unwrap_or("_".to_owned()), Origin::Mir, ); - self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); - } - - /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of - /// the local assigned at `location`. - /// This is done by searching in statements succeeding `location` - /// and originating from `maybe_closure_span`. - pub(super) fn find_closure_span( - &self, - maybe_closure_span: Span, - location: Location, - ) -> Option<(Span, Span)> { - use rustc::hir::ExprKind::Closure; - use rustc::mir::AggregateKind; - - let local = match self.mir[location.block] - .statements - .get(location.statement_index) - { - Some(&Statement { - kind: StatementKind::Assign(Place::Local(local), _), - .. - }) => local, - _ => return None, - }; - - for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { - if maybe_closure_span != stmt.source_info.span { - break; - } + borrow_spans.var_span_label(&mut err, { + let place = &borrow.borrowed_place; + let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); - if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { - if let AggregateKind::Closure(def_id, _) = **kind { - debug!("find_closure_span: found closure {:?}", places); + format!("borrow occurs due to use of `{}` in closure", desc_place) + }); - return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { - let args_span = if let Closure(_, _, _, span, _) = - self.tcx.hir.expect_expr(node_id).node - { - span - } else { - return None; - }; - - self.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 => - { - debug!( - "find_closure_span: found captured local {:?}", - l - ); - return Some(v.span); - } - _ => {} - } - } - None - }) - .map(|var_span| (args_span, var_span)) - } else { - None - }; - } - } - } - - None + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); + err.buffer(&mut self.errors_buffer); } pub(super) fn report_conflicting_borrow( @@ -274,14 +254,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, ) { - let issued_span = self.retrieve_borrow_span(issued_borrow); + let issued_spans = self.retrieve_borrow_spans(issued_borrow); + let issued_span = issued_spans.args_or_use(); - let new_closure_span = self.find_closure_span(span, context.loc); - let span = new_closure_span.map(|(args, _)| args).unwrap_or(span); - let old_closure_span = self.find_closure_span(issued_span, issued_borrow.reserve_location); - let issued_span = old_closure_span - .map(|(args, _)| args) - .unwrap_or(issued_span); + let borrow_spans = self.borrow_spans(span, context.loc); + let span = borrow_spans.args_or_use(); let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); let tcx = self.tcx; @@ -368,23 +345,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(), }; - if let Some((_, var_span)) = old_closure_span { - let place = &issued_borrow.borrowed_place; - let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); - - err.span_label( - var_span, + if issued_spans == borrow_spans { + borrow_spans.var_span_label( + &mut err, format!( - "previous borrow occurs due to use of `{}` in closure", + "borrows occur due to use of `{}` in closure", desc_place ), ); - } + } else { + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_place(borrow_place).unwrap_or("_".to_owned()); + issued_spans.var_span_label( + &mut err, + format!( + "first borrow occurs due to use of `{}` in closure", + borrow_place_desc + ), + ); - if let Some((_, var_span)) = new_closure_span { - err.span_label( - var_span, - format!("borrow occurs due to use of `{}` in closure", desc_place), + borrow_spans.var_span_label( + &mut err, + format!("second borrow occurs due to use of `{}` in closure", desc_place), ); } @@ -407,7 +389,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .last() .unwrap(); - let borrow_span = self.mir.source_info(borrow.reserve_location).span; + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.var_or_use(); + let proper_span = match *root_place { Place::Local(local) => self.mir.local_decls[local].source_info.span, _ => drop_span, @@ -427,30 +411,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.access_place_error_reported .insert((root_place.clone(), borrow_span)); - match &self.describe_place(&borrow.borrowed_place) { - Some(name) => { - self.report_local_value_does_not_live_long_enough( - context, - name, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - kind.map(|k| (k, place_span.0)), - ); - } - None => { - self.report_temporary_value_does_not_live_long_enough( - context, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - ); - } - } + let mut err = match &self.describe_place(&borrow.borrowed_place) { + Some(name) => self.report_local_value_does_not_live_long_enough( + context, + name, + &scope_tree, + &borrow, + drop_span, + borrow_span, + proper_span, + kind.map(|k| (k, place_span.0)), + ), + None => self.report_temporary_value_does_not_live_long_enough( + context, + &scope_tree, + &borrow, + drop_span, + borrow_span, + proper_span, + ), + }; + + borrow_spans.args_span_label(&mut err, "value captured here"); + + err.buffer(&mut self.errors_buffer); } fn report_local_value_does_not_live_long_enough( @@ -463,7 +447,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { borrow_span: Span, _proper_span: Span, kind_place: Option<(WriteKind, &Place<'tcx>)>, - ) { + ) -> DiagnosticBuilder<'cx> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -481,7 +465,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err); - err.buffer(&mut self.errors_buffer); + err } fn report_temporary_value_does_not_live_long_enough( @@ -492,7 +476,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, _borrow_span: Span, proper_span: Span, - ) { + ) -> DiagnosticBuilder<'cx> { debug!( "report_temporary_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -507,7 +491,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(drop_span, "temporary value only lives until here"); self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); + err } pub(super) fn report_illegal_mutation_of_borrowed( @@ -516,14 +500,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (place, span): (&Place<'tcx>, Span), loan: &BorrowData<'tcx>, ) { + let loan_spans = self.retrieve_borrow_spans(loan); + let loan_span = loan_spans.args_or_use(); + let tcx = self.tcx; let mut err = tcx.cannot_assign_to_borrowed( span, - self.retrieve_borrow_span(loan), + loan_span, &self.describe_place(place).unwrap_or("_".to_owned()), Origin::Mir, ); + loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); + self.explain_why_borrow_contains_point(context, loan, None, &mut err); err.buffer(&mut self.errors_buffer); @@ -556,12 +545,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // PATTERN;) then make the error refer to that local, rather than the // place being assigned later. let (place_description, assigned_span) = match local_decl { - Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Clear), .. }) - | Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Set( - BindingForm::Var(VarBindingForm { - opt_match_place: None, .. - }))), ..}) - | Some(LocalDecl { is_user_variable: None, .. }) + Some(LocalDecl { + is_user_variable: Some(ClearCrossCrate::Clear), + .. + }) + | Some(LocalDecl { + is_user_variable: + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + opt_match_place: None, + .. + }))), + .. + }) + | Some(LocalDecl { + is_user_variable: None, + .. + }) | None => (self.describe_place(place), assigned_span), Some(decl) => (self.describe_place(err_place), decl.source_info.span), }; @@ -647,8 +646,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Projection(ref proj) => { match proj.elem { ProjectionElem::Deref => { - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.tcx); if let Some(field) = upvar_field_projection { let var_index = field.index(); let name = self.mir.upvar_decls[var_index].debug_name.to_string(); @@ -666,8 +665,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &including_downcast, )?; } else if let Place::Local(local) = proj.base { - if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) - = self.mir.local_decls[local].is_user_variable { + if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) = + self.mir.local_decls[local].is_user_variable + { self.append_place_to_string( &proj.base, buf, @@ -708,8 +708,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ProjectionElem::Field(field, _ty) => { autoderef = true; - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.tcx); if let Some(field) = upvar_field_projection { let var_index = field.index(); let name = self.mir.upvar_decls[var_index].debug_name.to_string(); @@ -810,7 +810,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ty::TyAdt(def, _) => if def.is_enum() { field.index().to_string() } else { - def.non_enum_variant().fields[field.index()].ident.to_string() + def.non_enum_variant().fields[field.index()] + .ident + .to_string() }, ty::TyTuple(_) => field.index().to_string(), ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { @@ -839,11 +841,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - // Retrieve span of given borrow from the current MIR representation - crate fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { - self.mir.source_info(borrow.reserve_location).span - } - // Retrieve type of a place for the current MIR representation fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { match place { @@ -860,3 +857,205 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } + +// The span(s) associated to a use of a place. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub(super) enum UseSpans { + // The access is caused by capturing a variable for a closure. + ClosureUse { + // The span of the args of the closure, including the `move` keyword if + // it's present. + args_span: Span, + // The span of the first use of the captured variable inside the closure. + var_span: Span + }, + // This access has a single span associated to it: common case. + OtherUse(Span), +} + +impl UseSpans { + pub(super) fn args_or_use(self) -> Span { + match self { + UseSpans::ClosureUse { + args_span: span, .. + } + | UseSpans::OtherUse(span) => span, + } + } + + pub(super) fn var_or_use(self) -> Span { + match self { + UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span, + } + } + + // Add a span label to the arguments of the closure, if it exists. + pub(super) fn args_span_label(self, err: &mut DiagnosticBuilder, message: impl Into) { + if let UseSpans::ClosureUse { args_span, .. } = self { + err.span_label(args_span, message); + } + } + + // Add a span label to the use of the captured variable, if it exists. + pub(super) fn var_span_label(self, err: &mut DiagnosticBuilder, message: impl Into) { + if let UseSpans::ClosureUse { var_span, .. } = self { + err.span_label(var_span, message); + } + } + + pub(super) fn for_closure(self) -> bool { + match self { + UseSpans::ClosureUse { .. } => true, + UseSpans::OtherUse(_) => false, + } + } + + pub(super) fn or_else(self, if_other: F) -> Self + where + F: FnOnce() -> Self, + { + match self { + closure @ UseSpans::ClosureUse { .. } => closure, + UseSpans::OtherUse(_) => if_other(), + } + } +} + +impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { + /// Finds the spans associated to a move or copy of move_place at location. + pub(super) fn move_spans( + &self, + moved_place: &Place<'tcx>, // Could also be an upvar. + location: Location, + ) -> UseSpans { + use self::UseSpans::*; + use rustc::hir::ExprKind::Closure; + use rustc::mir::AggregateKind; + + let stmt = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(stmt) => stmt, + None => return OtherUse(self.mir.source_info(location).span), + }; + + if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { + if let AggregateKind::Closure(def_id, _) = **kind { + debug!("find_closure_move_span: found closure {:?}", places); + + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Closure(_, _, _, args_span, _) = self.tcx.hir.expect_expr(node_id).node { + if let Some(var_span) = self.tcx.with_freevars(node_id, |freevars| { + for (v, place) in freevars.iter().zip(places) { + match place { + Operand::Copy(place) | Operand::Move(place) + if moved_place == place => + { + debug!( + "find_closure_move_span: found captured local {:?}", + place + ); + return Some(v.span); + } + _ => {} + } + } + None + }) { + return ClosureUse { + args_span, + var_span, + }; + } + } + } + } + } + + return OtherUse(stmt.source_info.span); + } + + /// Finds the span of arguments of a closure (within `maybe_closure_span`) + /// and its usage of the local assigned at `location`. + /// This is done by searching in statements succeeding `location` + /// and originating from `maybe_closure_span`. + pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans { + use self::UseSpans::*; + use rustc::hir::ExprKind::Closure; + use rustc::mir::AggregateKind; + + let local = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(&Statement { + kind: StatementKind::Assign(Place::Local(local), _), + .. + }) => local, + _ => return OtherUse(use_span), + }; + + if self.mir.local_kind(local) != LocalKind::Temp { + // operands are always temporaries. + return OtherUse(use_span); + } + + for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { + if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { + if let AggregateKind::Closure(def_id, _) = **kind { + debug!("find_closure_borrow_span: found closure {:?}", places); + + return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + let args_span = if let Closure(_, _, _, span, _) = + self.tcx.hir.expect_expr(node_id).node + { + span + } else { + return OtherUse(use_span); + }; + + self.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 => + { + debug!( + "find_closure_borrow_span: found captured local \ + {:?}", + l + ); + return Some(v.span); + } + _ => {} + } + } + None + }).map(|var_span| ClosureUse { + args_span, + var_span, + }).unwrap_or(OtherUse(use_span)) + } else { + OtherUse(use_span) + }; + } + } + + if use_span != stmt.source_info.span { + break; + } + } + + OtherUse(use_span) + } + + /// Helper to retrieve span(s) of given borrow from the current MIR + /// representation + pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData) -> UseSpans { + let span = self.mir.source_info(borrow.reserve_location).span; + self.borrow_spans(span, borrow.reserve_location) + } +} diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4596c7be1c557..320d3a4720321 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1542,7 +1542,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if borrow_of_local_data(&borrow.borrowed_place) { let err = self.tcx .cannot_borrow_across_generator_yield( - self.retrieve_borrow_span(borrow), + self.retrieve_borrow_spans(borrow).var_or_use(), yield_span, Origin::Mir, ); diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index cd2de3247cfba..e8862320ddf3f 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -160,7 +160,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let act; let acted_on; - let span = match error_access { AccessKind::Move => { err = self.tcx @@ -180,31 +179,23 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { act = "borrow as mutable"; acted_on = "borrowed as mutable"; - let closure_span = self.find_closure_span(span, location); - if let Some((args, var)) = closure_span { - err = self.tcx.cannot_borrow_path_as_mutable_because( - args, - &item_msg, - &reason, - Origin::Mir, - ); - err.span_label( - var, - format!( - "mutable borrow occurs due to use of `{}` in closure", - self.describe_place(access_place).unwrap(), - ), - ); - args - } else { - err = self.tcx.cannot_borrow_path_as_mutable_because( - span, - &item_msg, - &reason, - Origin::Mir, - ); - span - } + let borrow_spans = self.borrow_spans(span, location); + let borrow_span = borrow_spans.args_or_use(); + err = self.tcx.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + Origin::Mir, + ); + borrow_spans.var_span_label( + &mut err, + format!( + "mutable borrow occurs due to use of `{}` in closure", + // always Some() if the message is printed. + self.describe_place(access_place).unwrap_or(String::new()), + ) + ); + borrow_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 d98bba72f7a33..5098b24adc367 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -62,18 +62,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); match find_use::find(mir, regioncx, tcx, region_sub, context.loc) { - Some(Cause::LiveVar(_local, location)) => { - if self.is_borrow_location_in_loop(context.loc) { - err.span_label( - mir.source_info(location).span, - "borrow used here in later iteration of loop".to_string(), - ); + Some(Cause::LiveVar(local, location)) => { + let span = mir.source_info(location).span; + let spans = self.move_spans(&Place::Local(local), location) + .or_else(|| self.borrow_spans(span, location)); + let message = if self.is_borrow_location_in_loop(context.loc) { + if spans.for_closure() { + "borrow captured here by closure in later iteration of loop" + } else { + "borrow used here in later iteration of loop" + } } else { - err.span_label( - mir.source_info(location).span, - "borrow later used here".to_string(), - ); - } + if spans.for_closure() { + "borrow later captured here by closure" + } else { + "borrow later used here" + } + }; + err.span_label(spans.var_or_use(), message); } Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name { diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 2d6b6cea03019..0a53361df6e95 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -203,8 +203,15 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { desc, OGN = o ); - err.span_label(old_loan_span, "first closure is constructed here"); - err.span_label(new_loan_span, "second closure is constructed here"); + if old_loan_span == new_loan_span { + err.span_label( + old_loan_span, + "closures are constructed here in different iterations of loop" + ); + } else { + err.span_label(old_loan_span, "first closure is constructed here"); + err.span_label(new_loan_span, "second closure is constructed here"); + } if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, "borrow from first closure ends here"); } From 5639e2173b2506ed540ca4a563f0e63731e56bcb Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 1 Aug 2018 20:40:06 +0100 Subject: [PATCH 2/3] Tests for closure spans --- src/test/ui/nll/closure-access-spans.rs | 68 ++++++++ src/test/ui/nll/closure-access-spans.stderr | 110 +++++++++++++ src/test/ui/nll/closure-borrow-spans.rs | 112 +++++++++++++ src/test/ui/nll/closure-borrow-spans.stderr | 172 ++++++++++++++++++++ src/test/ui/nll/closure-move-spans.rs | 33 ++++ src/test/ui/nll/closure-move-spans.stderr | 39 +++++ src/test/ui/nll/closure-use-spans.rs | 33 ++++ src/test/ui/nll/closure-use-spans.stderr | 33 ++++ src/test/ui/nll/closures-in-loops.rs | 36 ++++ src/test/ui/nll/closures-in-loops.stderr | 30 ++++ 10 files changed, 666 insertions(+) create mode 100644 src/test/ui/nll/closure-access-spans.rs create mode 100644 src/test/ui/nll/closure-access-spans.stderr create mode 100644 src/test/ui/nll/closure-borrow-spans.rs create mode 100644 src/test/ui/nll/closure-borrow-spans.stderr create mode 100644 src/test/ui/nll/closure-move-spans.rs create mode 100644 src/test/ui/nll/closure-move-spans.stderr create mode 100644 src/test/ui/nll/closure-use-spans.rs create mode 100644 src/test/ui/nll/closure-use-spans.stderr create mode 100644 src/test/ui/nll/closures-in-loops.rs create mode 100644 src/test/ui/nll/closures-in-loops.stderr diff --git a/src/test/ui/nll/closure-access-spans.rs b/src/test/ui/nll/closure-access-spans.rs new file mode 100644 index 0000000000000..b49436fabcf74 --- /dev/null +++ b/src/test/ui/nll/closure-access-spans.rs @@ -0,0 +1,68 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that accesses due to a closure capture give a special note + +#![feature(nll)] + +fn closure_imm_capture_conflict(mut x: i32) { + let r = &mut x; + || x; //~ ERROR + r.use_mut(); +} + +fn closure_mut_capture_conflict(mut x: i32) { + let r = &mut x; + || x = 2; //~ ERROR + r.use_mut(); +} + +fn closure_unique_capture_conflict(mut x: &mut i32) { + let r = &mut x; + || *x = 2; //~ ERROR + r.use_mut(); +} + +fn closure_copy_capture_conflict(mut x: i32) { + let r = &mut x; + move || x; //~ ERROR + r.use_ref(); +} + +fn closure_move_capture_conflict(mut x: String) { + let r = &x; + || x; //~ ERROR + r.use_ref(); +} + +fn closure_imm_capture_moved(mut x: String) { + let r = x; + || x.len(); //~ ERROR +} + +fn closure_mut_capture_moved(mut x: String) { + let r = x; + || x = String::new(); //~ ERROR +} + +fn closure_unique_capture_moved(x: &mut String) { + let r = x; + || *x = String::new(); //~ ERROR +} + +fn closure_move_capture_moved(x: &mut String) { + let r = x; + || x; //~ ERROR +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr new file mode 100644 index 0000000000000..0042b5d7d529b --- /dev/null +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -0,0 +1,110 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/closure-access-spans.rs:17:5 + | +LL | let r = &mut x; + | ------ mutable borrow occurs here +LL | || x; //~ ERROR + | ^^ - second borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | r.use_mut(); + | - borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closure-access-spans.rs:23:5 + | +LL | let r = &mut x; + | ------ first mutable borrow occurs here +LL | || x = 2; //~ ERROR + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | r.use_mut(); + | - borrow later used here + +error[E0500]: closure requires unique access to `x` but it is already borrowed + --> $DIR/closure-access-spans.rs:29:5 + | +LL | let r = &mut x; + | ------ borrow occurs here +LL | || *x = 2; //~ ERROR + | ^^ - second borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | r.use_mut(); + | - borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/closure-access-spans.rs:35:13 + | +LL | let r = &mut x; + | ------ borrow of `x` occurs here +LL | move || x; //~ ERROR + | ^ use of borrowed `x` +LL | r.use_ref(); + | - borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-access-spans.rs:41:5 + | +LL | let r = &x; + | -- borrow of `x` occurs here +LL | || x; //~ ERROR + | ^^ - move occurs due to use in closure + | | + | move out of `x` occurs here +LL | r.use_ref(); + | - borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:47:5 + | +LL | let r = x; + | - value moved here +LL | || x.len(); //~ ERROR + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:52:5 + | +LL | let r = x; + | - value moved here +LL | || x = String::new(); //~ ERROR + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:57:5 + | +LL | let r = x; + | - value moved here +LL | || *x = String::new(); //~ ERROR + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | + = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/closure-access-spans.rs:62:5 + | +LL | let r = x; + | - value moved here +LL | || x; //~ ERROR + | ^^ - use occurs due to use in closure + | | + | value used here after move + | + = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait + +error: aborting due to 9 previous errors + +Some errors occurred: E0382, E0499, E0500, E0502, E0503, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/closure-borrow-spans.rs b/src/test/ui/nll/closure-borrow-spans.rs new file mode 100644 index 0000000000000..d62dc27dade8f --- /dev/null +++ b/src/test/ui/nll/closure-borrow-spans.rs @@ -0,0 +1,112 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that existing borrows due to a closure capture give a special note + +#![feature(nll)] + +fn move_while_borrowed(x: String) { + let f = || x.len(); + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed(mut x: i32) { + let f = || x; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed() { + let f; + { + let x = 1; + f = || x; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed(mut x: i32) { + let f = || x; + x = 1; //~ ERROR + f.use_ref(); +} + +fn copy_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = &x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed_mut() { + let f; + { + let mut x = 1; + f = || x = 0; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + x = 1; //~ ERROR + f.use_ref(); +} + +fn copy_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + let y = &x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed_unique(mut x: &mut i32) { + let f = || *x = 0; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed_unique() { + let mut z = 1; + let f; + { + let x = &mut z; + f = || *x = 0; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + *x = 1; //~ ERROR + f.use_ref(); +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr new file mode 100644 index 0000000000000..1b9420b3c0bf3 --- /dev/null +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -0,0 +1,172 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:17:13 + | +LL | let f = || x.len(); + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | let y = x; //~ ERROR + | ^ move out of `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/closure-borrow-spans.rs:23:13 + | +LL | let f = || x; + | -- - first borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ mutable borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:31:16 + | +LL | f = || x; //~ ERROR + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | - borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:38:5 + | +LL | let f = || x; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 1; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/closure-borrow-spans.rs:44:13 + | +LL | let f = || x = 0; + | -- - borrow occurs due to use of `x` in closure + | | + | borrow of `x` occurs here +LL | let y = x; //~ ERROR + | ^ use of borrowed `x` +LL | f.use_ref(); + | - borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/closure-borrow-spans.rs:50:13 + | +LL | let f = || x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | let y = &x; //~ ERROR + | ^^ immutable borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closure-borrow-spans.rs:56:13 + | +LL | let f = || x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ second mutable borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:64:16 + | +LL | f = || x = 0; //~ ERROR + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | - borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:71:5 + | +LL | let f = || x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 1; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:77:13 + | +LL | let f = || *x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | let y = x; //~ ERROR + | ^ move out of `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/closure-borrow-spans.rs:83:13 + | +LL | let f = || *x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | let y = &x; //~ ERROR + | ^^ borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access + --> $DIR/closure-borrow-spans.rs:89:13 + | +LL | let f = || *x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:98:17 + | +LL | f = || *x = 0; //~ ERROR + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | - borrow later used here + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:105:5 + | +LL | let f = || *x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `*x` occurs here +LL | *x = 1; //~ ERROR + | ^^^^^^ assignment to borrowed `*x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error: aborting due to 14 previous errors + +Some errors occurred: E0499, E0501, E0502, E0503, E0505, E0506, E0597. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/nll/closure-move-spans.rs b/src/test/ui/nll/closure-move-spans.rs new file mode 100644 index 0000000000000..7e836275c8bff --- /dev/null +++ b/src/test/ui/nll/closure-move-spans.rs @@ -0,0 +1,33 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that moves due to a closure capture give a special note + +#![feature(nll)] + +fn move_after_move(x: String) { + || x; + let y = x; //~ ERROR +} + +fn borrow_after_move(x: String) { + || x; + let y = &x; //~ ERROR +} + +fn borrow_mut_after_move(mut x: String) { + || x; + let y = &mut x; //~ ERROR +} + +fn fn_ref(f: F) -> F { f } +fn fn_mut(f: F) -> F { f } + +fn main() {} diff --git a/src/test/ui/nll/closure-move-spans.stderr b/src/test/ui/nll/closure-move-spans.stderr new file mode 100644 index 0000000000000..80b7b4246a747 --- /dev/null +++ b/src/test/ui/nll/closure-move-spans.stderr @@ -0,0 +1,39 @@ +error[E0382]: use of moved value: `x` + --> $DIR/closure-move-spans.rs:17:13 + | +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = x; //~ ERROR + | ^ value used here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-move-spans.rs:22:13 + | +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = &x; //~ ERROR + | ^^ value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-move-spans.rs:27:13 + | +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/closure-use-spans.rs b/src/test/ui/nll/closure-use-spans.rs new file mode 100644 index 0000000000000..7ab382a96bbb4 --- /dev/null +++ b/src/test/ui/nll/closure-use-spans.rs @@ -0,0 +1,33 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that liveness due to a closure capture gives a special note + +#![feature(nll)] + +fn use_as_borrow_capture(mut x: i32) { + let y = &x; + x = 0; //~ ERROR + || *y; +} + +fn use_as_borrow_mut_capture(mut x: i32) { + let y = &mut x; + x = 0; //~ ERROR + || *y = 1; +} + +fn use_as_move_capture(mut x: i32) { + let y = &x; + x = 0; //~ ERROR + move || *y; +} + +fn main() {} diff --git a/src/test/ui/nll/closure-use-spans.stderr b/src/test/ui/nll/closure-use-spans.stderr new file mode 100644 index 0000000000000..7e5f9621d0955 --- /dev/null +++ b/src/test/ui/nll/closure-use-spans.stderr @@ -0,0 +1,33 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:17:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +LL | x = 0; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | || *y; + | - borrow later captured here by closure + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:23:5 + | +LL | let y = &mut x; + | ------ borrow of `x` occurs here +LL | x = 0; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | || *y = 1; + | - borrow later captured here by closure + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:29:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +LL | x = 0; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | move || *y; + | - borrow later captured here by closure + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/closures-in-loops.rs b/src/test/ui/nll/closures-in-loops.rs new file mode 100644 index 0000000000000..c6113f3a9c50a --- /dev/null +++ b/src/test/ui/nll/closures-in-loops.rs @@ -0,0 +1,36 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test messages where a closure capture conflicts with itself because it's in +// a loop. + +#![feature(nll)] + +fn repreated_move(x: String) { + for i in 0..10 { + || x; //~ ERROR + } +} + +fn repreated_mut_borrow(mut x: String) { + let mut v = Vec::new(); + for i in 0..10 { + v.push(|| x = String::new()); //~ ERROR + } +} + +fn repreated_unique_borrow(x: &mut String) { + let mut v = Vec::new(); + for i in 0..10 { + v.push(|| *x = String::new()); //~ ERROR + } +} + +fn main() {} diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr new file mode 100644 index 0000000000000..9758a80362000 --- /dev/null +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -0,0 +1,30 @@ +error[E0382]: use of moved value: `x` + --> $DIR/closures-in-loops.rs:18:9 + | +LL | || x; //~ ERROR + | ^^ - use occurs due to use in closure + | | + | 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 + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closures-in-loops.rs:25:16 + | +LL | v.push(|| x = String::new()); //~ ERROR + | ^^ - borrows occur due to use of `x` in closure + | | + | mutable borrow starts here in previous iteration of loop + +error[E0524]: two closures require unique access to `x` at the same time + --> $DIR/closures-in-loops.rs:32:16 + | +LL | v.push(|| *x = String::new()); //~ ERROR + | ^^ - borrows occur due to use of `x` in closure + | | + | closures are constructed here in different iterations of loop + +error: aborting due to 3 previous errors + +Some errors occurred: E0382, E0499, E0524. +For more information about an error, try `rustc --explain E0382`. From 12af36a5c4638755be622c220efadffb1864f2ab Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 1 Aug 2018 21:02:10 +0100 Subject: [PATCH 3/3] Update tests for new spans for nll errors involving closures --- .../borrowck/borrowck-closures-two-mut.stderr | 20 +-- ...rrowck-escaping-closure-error-1.nll.stderr | 6 +- ...rrowck-escaping-closure-error-2.nll.stderr | 6 +- src/test/ui/error-codes/E0504.nll.stderr | 17 ++- src/test/ui/issue-11192.nll.stderr | 2 +- src/test/ui/issue-11873.nll.stderr | 4 +- src/test/ui/issue-18783.nll.stderr | 8 +- src/test/ui/issue-24357.nll.stderr | 4 +- ...e-27282-move-match-input-into-guard.stderr | 10 +- ...27282-mutate-before-diverging-arm-1.stderr | 2 +- ...27282-mutate-before-diverging-arm-2.stderr | 2 +- src/test/ui/issue-4335.nll.stderr | 6 +- src/test/ui/issue-6801.nll.stderr | 4 +- src/test/ui/nll/closure-captures.rs | 2 +- .../escape-upvar-nested.rs | 4 +- .../escape-upvar-nested.stderr | 26 ++-- .../escape-upvar-ref.stderr | 6 +- src/test/ui/nll/issue-51268.stderr | 2 +- ...borrow-params-issue-29793-small.nll.stderr | 120 ++++++++++++------ src/test/ui/regions-nested-fns-2.nll.stderr | 17 +-- ...owck-call-is-borrow-issue-12224.nll.stderr | 25 ++-- ...d-is-not-static-ensures-scoping.nll.stderr | 21 ++- 22 files changed, 184 insertions(+), 130 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr index a4f8e8b408ba5..6186c3839193d 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr @@ -77,11 +77,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:24:24 | LL | let c1 = to_fn_mut(|| x = 4); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once @@ -92,11 +92,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:36:24 | LL | let c1 = to_fn_mut(|| set(&mut x)); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once @@ -107,11 +107,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:44:24 | LL | let c1 = to_fn_mut(|| x = 5); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once @@ -122,11 +122,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:52:24 | LL | let c1 = to_fn_mut(|| x = 5); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here ... @@ -137,11 +137,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:65:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here ... diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr index b15f156b7c201..426419a7b3b7f 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr @@ -1,8 +1,10 @@ error[E0597]: `books` does not live long enough - --> $DIR/borrowck-escaping-closure-error-1.rs:23:11 + --> $DIR/borrowck-escaping-closure-error-1.rs:23:14 | LL | spawn(|| books.push(4)); - | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | -- ^^^^^ borrowed value does not live long enough + | | + | value captured here LL | //~^ ERROR E0373 LL | } | - `books` dropped here while still borrowed diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr index 8c643973af67b..d5f3a0ed6d82e 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr @@ -1,8 +1,10 @@ error[E0597]: `books` does not live long enough - --> $DIR/borrowck-escaping-closure-error-2.rs:21:14 + --> $DIR/borrowck-escaping-closure-error-2.rs:21:17 | LL | Box::new(|| books.push(4)) - | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | -- ^^^^^ borrowed value does not live long enough + | | + | value captured here LL | //~^ ERROR E0373 LL | } | - `books` dropped here while still borrowed diff --git a/src/test/ui/error-codes/E0504.nll.stderr b/src/test/ui/error-codes/E0504.nll.stderr index ec30bb306fc3f..6f4823326ffa6 100644 --- a/src/test/ui/error-codes/E0504.nll.stderr +++ b/src/test/ui/error-codes/E0504.nll.stderr @@ -1,17 +1,16 @@ error[E0505]: cannot move out of `fancy_num` because it is borrowed --> $DIR/E0504.rs:19:13 | -LL | let fancy_ref = &fancy_num; - | ---------- borrow of `fancy_num` occurs here +LL | let fancy_ref = &fancy_num; + | ---------- borrow of `fancy_num` occurs here LL | -LL | let x = move || { - | _____________^ -LL | | println!("child function: {}", fancy_num.num); //~ ERROR E0504 -LL | | }; - | |_____^ move out of `fancy_num` occurs here +LL | let x = move || { + | ^^^^^^^ move out of `fancy_num` occurs here +LL | println!("child function: {}", fancy_num.num); //~ ERROR E0504 + | --------- move occurs due to use in closure ... -LL | println!("main function: {}", fancy_ref.num); - | ------------- borrow later used here +LL | println!("main function: {}", fancy_ref.num); + | ------------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/issue-11192.nll.stderr b/src/test/ui/issue-11192.nll.stderr index d5a67083a23b8..a7e6c9f2b3371 100644 --- a/src/test/ui/issue-11192.nll.stderr +++ b/src/test/ui/issue-11192.nll.stderr @@ -5,7 +5,7 @@ LL | let mut test = |foo: &Foo| { | ----------- mutable borrow occurs here LL | println!("access {}", foo.x); LL | ptr = box Foo { x: ptr.x + 1 }; - | --- previous borrow occurs due to use of `ptr` in closure + | --- first borrow occurs due to use of `ptr` in closure ... LL | test(&*ptr); | -----^^^^^- diff --git a/src/test/ui/issue-11873.nll.stderr b/src/test/ui/issue-11873.nll.stderr index c12cbbfdd53a1..bf4fed06dee21 100644 --- a/src/test/ui/issue-11873.nll.stderr +++ b/src/test/ui/issue-11873.nll.stderr @@ -2,7 +2,9 @@ error[E0505]: cannot move out of `v` because it is borrowed --> $DIR/issue-11873.rs:14:14 | LL | let mut f = || v.push(2); - | ------------ borrow of `v` occurs here + | -- - borrow occurs due to use in closure + | | + | borrow of `v` occurs here LL | let _w = v; //~ ERROR: cannot move out of `v` | ^ move out of `v` occurs here LL | diff --git a/src/test/ui/issue-18783.nll.stderr b/src/test/ui/issue-18783.nll.stderr index 6bb7b4229d747..8acdc73bf0e68 100644 --- a/src/test/ui/issue-18783.nll.stderr +++ b/src/test/ui/issue-18783.nll.stderr @@ -2,11 +2,11 @@ error[E0499]: cannot borrow `y` as mutable more than once at a time --> $DIR/issue-18783.rs:17:21 | LL | c.push(Box::new(|| y = 0)); - | -- - previous borrow occurs due to use of `y` in closure + | -- - first borrow occurs due to use of `y` in closure | | | first mutable borrow occurs here LL | c.push(Box::new(|| y = 0)); - | ^^ - borrow occurs due to use of `y` in closure + | ^^ - second borrow occurs due to use of `y` in closure | | | second mutable borrow occurs here LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time @@ -17,11 +17,11 @@ error[E0499]: cannot borrow `y` as mutable more than once at a time --> $DIR/issue-18783.rs:26:29 | LL | Push::push(&c, Box::new(|| y = 0)); - | -- - previous borrow occurs due to use of `y` in closure + | -- - first borrow occurs due to use of `y` in closure | | | first mutable borrow occurs here LL | Push::push(&c, Box::new(|| y = 0)); - | ^^ - borrow occurs due to use of `y` in closure + | ^^ - second borrow occurs due to use of `y` in closure | | | second mutable borrow occurs here LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time diff --git a/src/test/ui/issue-24357.nll.stderr b/src/test/ui/issue-24357.nll.stderr index f601a6fbc8850..e35f443548d90 100644 --- a/src/test/ui/issue-24357.nll.stderr +++ b/src/test/ui/issue-24357.nll.stderr @@ -2,7 +2,9 @@ error[E0382]: use of moved value: `x` --> $DIR/issue-24357.rs:16:12 | LL | let f = move || { let y = x; }; - | ---------------------- value moved here + | ------- - variable moved due to use in closure + | | + | value moved into closure here LL | //~^ NOTE value moved (into closure) here LL | let z = x; | ^ value used here after move diff --git a/src/test/ui/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issue-27282-move-match-input-into-guard.stderr index d264bf8d2734d..91c51bcd05825 100644 --- a/src/test/ui/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issue-27282-move-match-input-into-guard.stderr @@ -1,11 +1,13 @@ error[E0505]: cannot move out of `b` because it is borrowed - --> $DIR/issue-27282-move-match-input-into-guard.rs:26:16 + --> $DIR/issue-27282-move-match-input-into-guard.rs:26:17 | LL | match b { | - borrow of `b` occurs here LL | &mut false => {}, LL | _ if { (|| { let bar = b; *bar = false; })(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here + | ^^ - move occurs due to use in closure + | | + | move out of `b` occurs here ... LL | &mut true => { println!("You might think we should get here"); }, | --------- borrow later used here @@ -14,7 +16,9 @@ error[E0382]: use of moved value: `*b` --> $DIR/issue-27282-move-match-input-into-guard.rs:29:14 | LL | _ if { (|| { let bar = b; *bar = false; })(); - | ----------------------------------- value moved here + | -- - variable moved due to use in closure + | | + | value moved into closure here ... LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr index fb11090c222d0..a9d9651fb2a35 100644 --- a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr +++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr @@ -5,7 +5,7 @@ LL | match x { | - borrow occurs here ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | closure construction occurs here ... diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr index 6e643d30185f9..582d0fd678c07 100644 --- a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr +++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr @@ -5,7 +5,7 @@ LL | match x { | - borrow occurs here ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | closure construction occurs here ... diff --git a/src/test/ui/issue-4335.nll.stderr b/src/test/ui/issue-4335.nll.stderr index 40d7838a80325..4ccd24fa45921 100644 --- a/src/test/ui/issue-4335.nll.stderr +++ b/src/test/ui/issue-4335.nll.stderr @@ -5,10 +5,12 @@ LL | id(Box::new(|| *v)) | ^^ cannot move out of captured variable in an `FnMut` closure error[E0597]: `v` does not live long enough - --> $DIR/issue-4335.rs:16:17 + --> $DIR/issue-4335.rs:16:21 | LL | id(Box::new(|| *v)) - | ^^^^^ borrowed value does not live long enough + | -- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `v` dropped here while still borrowed diff --git a/src/test/ui/issue-6801.nll.stderr b/src/test/ui/issue-6801.nll.stderr index 5436397c68ead..3ca2f39470da7 100644 --- a/src/test/ui/issue-6801.nll.stderr +++ b/src/test/ui/issue-6801.nll.stderr @@ -2,7 +2,9 @@ error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/issue-6801.rs:29:13 | LL | let sq = || { *x * *x }; - | -------------- borrow of `x` occurs here + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here LL | LL | twice(x); //~ ERROR: cannot move out of | ^ move out of `x` occurs here diff --git a/src/test/ui/nll/closure-captures.rs b/src/test/ui/nll/closure-captures.rs index 03a22bb79a86b..16385ca2499cc 100644 --- a/src/test/ui/nll/closure-captures.rs +++ b/src/test/ui/nll/closure-captures.rs @@ -13,7 +13,7 @@ #![allow(unused)] #![feature(nll)] -// Should have one error per assigment +// Should have one error per assignment fn one_closure(x: i32) { || diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs index 598839f872e01..ce44903e6e6a8 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs @@ -27,8 +27,8 @@ fn test() { { let y = 22; - let mut closure = || { //~ ERROR `y` does not live long enough [E0597] - let mut closure1 = || p = &y; + let mut closure = || { + let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] closure1(); }; diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index bf12800e58d71..ed2ae2f27b57b 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -1,7 +1,7 @@ note: External requirements --> $DIR/escape-upvar-nested.rs:31:32 | -LL | let mut closure1 = || p = &y; +LL | let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] | ^^^^^^^^^ | = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [ @@ -16,9 +16,9 @@ LL | let mut closure1 = || p = &y; note: External requirements --> $DIR/escape-upvar-nested.rs:30:27 | -LL | let mut closure = || { //~ ERROR `y` does not live long enough [E0597] +LL | let mut closure = || { | ___________________________^ -LL | | let mut closure1 = || p = &y; +LL | | let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] LL | | closure1(); LL | | }; | |_________^ @@ -47,20 +47,18 @@ LL | | } = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough - --> $DIR/escape-upvar-nested.rs:30:27 + --> $DIR/escape-upvar-nested.rs:31:40 | -LL | let mut closure = || { //~ ERROR `y` does not live long enough [E0597] - | ___________________________^ -LL | | let mut closure1 = || p = &y; -LL | | closure1(); -LL | | }; - | |_________^ borrowed value does not live long enough +LL | let mut closure = || { + | -- value captured here +LL | let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] + | ^ borrowed value does not live long enough ... -LL | } - | - `y` dropped here while still borrowed +LL | } + | - `y` dropped here while still borrowed LL | -LL | deref(p); - | - borrow later used here +LL | deref(p); + | - borrow later used here error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index 4b0dad3bda022..8db56deeb1f7a 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -28,10 +28,12 @@ LL | | } = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough - --> $DIR/escape-upvar-ref.rs:33:27 + --> $DIR/escape-upvar-ref.rs:33:35 | LL | let mut closure = || p = &y; - | ^^^^^^^^^ borrowed value does not live long enough + | -- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed diff --git a/src/test/ui/nll/issue-51268.stderr b/src/test/ui/nll/issue-51268.stderr index 269bc368305cb..2ecfe03e7de62 100644 --- a/src/test/ui/nll/issue-51268.stderr +++ b/src/test/ui/nll/issue-51268.stderr @@ -8,7 +8,7 @@ LL | self.thing.bar(|| { | || LL | || //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502] LL | || &self.number; - | || ---- previous borrow occurs due to use of `self` in closure + | || ---- first borrow occurs due to use of `self` in closure LL | || }); | || ^ | ||__________| diff --git a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr index ae7193ef4fa79..d0d6bd4c78570 100644 --- a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr +++ b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr @@ -1,44 +1,54 @@ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:19:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:19:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:19:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:19:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:34:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:34:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:34:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:34:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:65:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:65:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed @@ -50,10 +60,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:65:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:65:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed @@ -65,10 +77,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:76:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:76:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed @@ -80,10 +94,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:76:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:76:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed @@ -95,10 +111,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:100:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:100:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -110,10 +128,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:100:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:100:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -125,10 +145,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:114:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:114:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -140,10 +162,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:114:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:114:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -155,10 +179,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:142:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:142:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -170,10 +196,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:142:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:142:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -185,10 +213,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:157:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:157:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -200,10 +230,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:157:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:157:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -215,10 +247,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:185:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:185:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -230,10 +264,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:185:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:185:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -245,10 +281,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:199:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:199:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -260,10 +298,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:199:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:199:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed diff --git a/src/test/ui/regions-nested-fns-2.nll.stderr b/src/test/ui/regions-nested-fns-2.nll.stderr index 13e34d85210a7..1b5bb7d500779 100644 --- a/src/test/ui/regions-nested-fns-2.nll.stderr +++ b/src/test/ui/regions-nested-fns-2.nll.stderr @@ -1,13 +1,14 @@ error[E0597]: `y` does not live long enough - --> $DIR/regions-nested-fns-2.rs:16:9 + --> $DIR/regions-nested-fns-2.rs:18:25 | -LL | / |z| { -LL | | //~^ ERROR E0373 -LL | | if false { &y } else { z } -LL | | }); - | |_________^ borrowed value does not live long enough -LL | } - | - `y` dropped here while still borrowed +LL | |z| { + | --- value captured here +LL | //~^ ERROR E0373 +LL | if false { &y } else { z } + | ^ borrowed value does not live long enough +LL | }); +LL | } + | - `y` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index b3563f1b6203c..c7dbc043cdaee 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -8,7 +8,7 @@ LL | f(Box::new(|| { | | LL | | //~^ ERROR: cannot borrow `f` as mutable more than once LL | | f((Box::new(|| {}))) - | | - borrow occurs due to use of `f` in closure + | | - second borrow occurs due to use of `f` in closure LL | | })); | |_______- borrow later used here @@ -37,18 +37,17 @@ LL | foo(f); error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16 | -LL | f(Box::new(|a| { - | _____-__________^ - | | | - | |_____borrow of `f` occurs here - | || -LL | || foo(f); -LL | || //~^ ERROR cannot move `f` into closure because it is borrowed -LL | || //~| ERROR cannot move out of captured outer variable in an `FnMut` closure -LL | || }), 3); - | ||_____^____- borrow later used here - | |_____| - | move out of `f` occurs here +LL | f(Box::new(|a| { + | - ^^^ move out of `f` occurs here + | | + | _____borrow of `f` occurs here + | | +LL | | foo(f); + | | - move occurs due to use in closure +LL | | //~^ ERROR cannot move `f` into closure because it is borrowed +LL | | //~| ERROR cannot move out of captured outer variable in an `FnMut` closure +LL | | }), 3); + | |__________- borrow later used here error: aborting due to 5 previous errors diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr index 1753f710b8842..c14cb7098933f 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr @@ -11,19 +11,18 @@ LL | bad.join(); | --- borrow later used here error[E0597]: `y` does not live long enough - --> $DIR/send-is-not-static-ensures-scoping.rs:29:16 + --> $DIR/send-is-not-static-ensures-scoping.rs:30:22 | -LL | scoped(|| { - | ________________^ -LL | | let _z = y; -LL | | //~^ ERROR `y` does not live long enough -LL | | }) - | |_________^ borrowed value does not live long enough -LL | }; - | - `y` dropped here while still borrowed +LL | scoped(|| { + | -- value captured here +LL | let _z = y; + | ^ borrowed value does not live long enough +... +LL | }; + | - `y` dropped here while still borrowed LL | -LL | bad.join(); - | --- borrow later used here +LL | bad.join(); + | --- borrow later used here error: aborting due to 2 previous errors