diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index dbcb63addb846..693219ec4b03f 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { + pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { let ty_vars = self.type_variables.borrow(); if let TypeVariableOrigin::TypeParameterDefinition(_, name) = diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c67453d2b201a..15b5edaa3d5d7 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -19,7 +19,7 @@ use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon}; use ty::{TyDynamic, TyInt, TyUint, TyInfer}; -use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; +use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; use std::cell::Cell; @@ -32,6 +32,12 @@ use syntax::ast::CRATE_NODE_ID; use syntax::symbol::{Symbol, InternedString}; use hir; +thread_local! { + /// Mechanism for highlighting of specific regions for display in NLL region inference errors. + /// Contains region to highlight and counter for number to use when highlighting. + static HIGHLIGHT_REGION: Cell> = Cell::new(None) +} + macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -562,6 +568,19 @@ pub fn parameterized(f: &mut F, PrintContext::new().parameterized(f, substs, did, projections) } +fn get_highlight_region() -> Option<(RegionVid, usize)> { + HIGHLIGHT_REGION.with(|hr| hr.get()) +} + +pub fn with_highlight_region(r: RegionVid, counter: usize, op: impl FnOnce() -> R) -> R { + HIGHLIGHT_REGION.with(|hr| { + assert_eq!(hr.get(), None); + hr.set(Some((r, counter))); + let r = op(); + hr.set(None); + r + }) +} impl<'a, T: Print> Print for &'a T { fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { @@ -733,7 +752,7 @@ define_print! { define_print! { () ty::RegionKind, (self, f, cx) { display { - if cx.is_verbose { + if cx.is_verbose || get_highlight_region().is_some() { return self.print_debug(f, cx); } @@ -905,6 +924,15 @@ impl fmt::Debug for ty::FloatVid { impl fmt::Debug for ty::RegionVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some((region, counter)) = get_highlight_region() { + debug!("RegionVid.fmt: region={:?} self={:?} counter={:?}", region, self, counter); + return if *self == region { + write!(f, "'{:?}", counter) + } else { + write!(f, "'_") + } + } + write!(f, "'_#{}r", self.index()) } } @@ -1022,9 +1050,11 @@ define_print! { TyRef(r, ty, mutbl) => { write!(f, "&")?; let s = r.print_to_string(cx); - write!(f, "{}", s)?; - if !s.is_empty() { - write!(f, " ")?; + if s != "'_" { + write!(f, "{}", s)?; + if !s.is_empty() { + write!(f, " ")?; + } } ty::TypeAndMut { ty, mutbl }.print(f, cx) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 1b540ef74be49..c2c5c6771b01f 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -31,9 +31,7 @@ mod var_name; enum ConstraintCategory { Cast, Assignment, - AssignmentToUpvar, Return, - CallArgumentToUpvar, CallArgument, Other, Boring, @@ -41,16 +39,13 @@ enum ConstraintCategory { impl fmt::Display for ConstraintCategory { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Must end with a space. Allows for empty names to be provided. match self { - ConstraintCategory::Assignment | ConstraintCategory::AssignmentToUpvar => { - write!(f, "assignment") - } - ConstraintCategory::Return => write!(f, "return"), - ConstraintCategory::Cast => write!(f, "cast"), - ConstraintCategory::CallArgument | ConstraintCategory::CallArgumentToUpvar => { - write!(f, "argument") - } - _ => write!(f, "free region"), + ConstraintCategory::Assignment => write!(f, "assignment "), + ConstraintCategory::Return => write!(f, "return "), + ConstraintCategory::Cast => write!(f, "cast "), + ConstraintCategory::CallArgument => write!(f, "argument "), + _ => write!(f, ""), } } } @@ -224,10 +219,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { "constraint_is_interesting: locations={:?} constraint={:?}", constraint.locations, constraint ); - if let Locations::Interesting(_) = constraint.locations { - true - } else { - false + + match constraint.locations { + Locations::Interesting(_) | Locations::All => true, + _ => false, } } @@ -320,45 +315,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - let category = match ( - category, + let (fr_is_local, outlived_fr_is_local): (bool, bool) = ( self.universal_regions.is_local_free_region(fr), self.universal_regions.is_local_free_region(outlived_fr), - ) { - (ConstraintCategory::Assignment, true, false) => ConstraintCategory::AssignmentToUpvar, - (ConstraintCategory::CallArgument, true, false) => { - ConstraintCategory::CallArgumentToUpvar - } - (category, _, _) => category, + ); + debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}", + fr_is_local, outlived_fr_is_local, category); + + match (category, fr_is_local, outlived_fr_is_local) { + (ConstraintCategory::Assignment, true, false) | + (ConstraintCategory::CallArgument, true, false) => + self.report_escaping_data_error(mir, infcx, mir_def_id, fr, outlived_fr, + category, span, errors_buffer), + _ => + self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local, + outlived_fr, outlived_fr_is_local, + category, span, errors_buffer), }; - - debug!("report_error: category={:?}", category); - match category { - ConstraintCategory::AssignmentToUpvar | ConstraintCategory::CallArgumentToUpvar => self - .report_closure_error( - mir, - infcx, - mir_def_id, - fr, - outlived_fr, - category, - span, - errors_buffer, - ), - _ => self.report_general_error( - mir, - infcx, - mir_def_id, - fr, - outlived_fr, - category, - span, - errors_buffer, - ), - } } - fn report_closure_error( + fn report_escaping_data_error( &self, mir: &Mir<'tcx>, infcx: &InferCtxt<'_, '_, 'tcx>, @@ -373,29 +349,23 @@ impl<'tcx> RegionInferenceContext<'tcx> { let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(infcx.tcx, mir, outlived_fr); + let escapes_from = if infcx.tcx.is_closure(mir_def_id) { "closure" } else { "function" }; + if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() { - return self.report_general_error( - mir, - infcx, - mir_def_id, - fr, - outlived_fr, - category, - span, - errors_buffer, - ); + return self.report_general_error(mir, infcx, mir_def_id, + fr, true, outlived_fr, false, + category, span, errors_buffer); } - let mut diag = infcx - .tcx - .sess - .struct_span_err(span, &format!("borrowed data escapes outside of closure")); + let mut diag = infcx.tcx.sess.struct_span_err( + span, &format!("borrowed data escapes outside of {}", escapes_from), + ); if let Some((outlived_fr_name, outlived_fr_span)) = outlived_fr_name_and_span { if let Some(name) = outlived_fr_name { diag.span_label( outlived_fr_span, - format!("`{}` is declared here, outside of the closure body", name), + format!("`{}` is declared here, outside of the {} body", name, escapes_from), ); } } @@ -404,13 +374,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let Some(name) = fr_name { diag.span_label( fr_span, - format!( - "`{}` is a reference that is only valid in the closure body", - name - ), + format!("`{}` is a reference that is only valid in the {} body", + name, escapes_from), ); - diag.span_label(span, format!("`{}` escapes the closure body here", name)); + diag.span_label(span, format!("`{}` escapes the {} body here", + name, escapes_from)); } } @@ -423,7 +392,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx: &InferCtxt<'_, '_, 'tcx>, mir_def_id: DefId, fr: RegionVid, + fr_is_local: bool, outlived_fr: RegionVid, + outlived_fr_is_local: bool, category: ConstraintCategory, span: Span, errors_buffer: &mut Vec, @@ -434,17 +405,28 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); let counter = &mut 1; - let fr_name = self.give_region_a_name(infcx.tcx, mir, mir_def_id, fr, counter, &mut diag); - let outlived_fr_name = - self.give_region_a_name(infcx.tcx, mir, mir_def_id, outlived_fr, counter, &mut diag); - - diag.span_label( - span, - format!( - "{} requires that `{}` must outlive `{}`", - category, fr_name, outlived_fr_name, - ), - ); + let fr_name = self.give_region_a_name( + infcx, mir, mir_def_id, fr, counter, &mut diag); + let outlived_fr_name = self.give_region_a_name( + infcx, mir, mir_def_id, outlived_fr, counter, &mut diag); + + let mir_def_name = if infcx.tcx.is_closure(mir_def_id) { "closure" } else { "function" }; + + match (category, outlived_fr_is_local, fr_is_local) { + (ConstraintCategory::Return, true, _) => { + diag.span_label(span, format!( + "{} was supposed to return data with lifetime `{}` but it is returning \ + data with lifetime `{}`", + mir_def_name, fr_name, outlived_fr_name, + )); + }, + _ => { + diag.span_label(span, format!( + "{}requires that `{}` must outlive `{}`", + category, fr_name, outlived_fr_name, + )); + }, + } diag.buffer(errors_buffer); } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index c0eca026331ba..8505d8e1ef39c 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -12,9 +12,11 @@ use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::infer::InferCtxt; use rustc::mir::Mir; use rustc::ty::subst::{Substs, UnpackedKind}; use rustc::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc::util::ppaux::with_highlight_region; use rustc_errors::DiagnosticBuilder; use syntax::ast::Name; use syntax::symbol::keywords; @@ -48,7 +50,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// and then return the name `'1` for us to use. crate fn give_region_a_name( &self, - tcx: TyCtxt<'_, '_, 'tcx>, + infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>, mir_def_id: DefId, fr: RegionVid, @@ -59,17 +61,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { assert!(self.universal_regions.is_universal_region(fr)); - self.give_name_from_error_region(tcx, mir_def_id, fr, counter, diag) + self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter, diag) .or_else(|| { self.give_name_if_anonymous_region_appears_in_arguments( - tcx, mir, mir_def_id, fr, counter, diag) + infcx, mir, mir_def_id, fr, counter, diag) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_upvars( - tcx, mir, fr, counter, diag) + infcx.tcx, mir, fr, counter, diag) }) .or_else(|| { - self.give_name_if_anonymous_region_appears_in_output(tcx, mir, fr, counter, diag) + self.give_name_if_anonymous_region_appears_in_output( + infcx.tcx, mir, fr, counter, diag) }) .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr)) } @@ -130,7 +133,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn give_name_if_anonymous_region_appears_in_arguments( &self, - tcx: TyCtxt<'_, '_, 'tcx>, + infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>, mir_def_id: DefId, fr: RegionVid, @@ -138,12 +141,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag: &mut DiagnosticBuilder<'_>, ) -> Option { let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); - let argument_index = self.get_argument_index_for_region(tcx, fr)?; + let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?; let arg_ty = self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index]; if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument( - tcx, + infcx, + mir, mir_def_id, fr, arg_ty, @@ -169,7 +173,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn give_name_if_we_can_match_hir_ty_from_argument( &self, - tcx: TyCtxt<'_, '_, 'tcx>, + infcx: &InferCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, mir_def_id: DefId, needle_fr: RegionVid, argument_ty: Ty<'tcx>, @@ -177,17 +182,24 @@ impl<'tcx> RegionInferenceContext<'tcx> { counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, ) -> Option { - let mir_node_id = tcx.hir.as_local_node_id(mir_def_id)?; - let fn_decl = tcx.hir.fn_decl(mir_node_id)?; + let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id)?; + let fn_decl = infcx.tcx.hir.fn_decl(mir_node_id)?; let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index]; match argument_hir_ty.node { // This indicates a variable with no type annotation, like // `|x|`... in that case, we can't highlight the type but // must highlight the variable. - hir::TyKind::Infer => None, + hir::TyKind::Infer => self.give_name_if_we_cannot_match_hir_ty( + infcx, + mir, + needle_fr, + argument_ty, + counter, + diag, + ), _ => self.give_name_if_we_can_match_hir_ty( - tcx, + infcx.tcx, needle_fr, argument_ty, argument_hir_ty, @@ -197,6 +209,49 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } + /// Attempts to highlight the specific part of a type in an argument + /// that has no type annotation. + /// For example, we might produce an annotation like this: + /// + /// ``` + /// | foo(|a, b| b) + /// | - - + /// | | | + /// | | has type `&'1 u32` + /// | has type `&'2 u32` + /// ``` + fn give_name_if_we_cannot_match_hir_ty( + &self, + infcx: &InferCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + needle_fr: RegionVid, + argument_ty: Ty<'tcx>, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let type_name = with_highlight_region(needle_fr, *counter, || { + infcx.extract_type_name(&argument_ty) + }); + + debug!("give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", + type_name, needle_fr); + let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() { + // Only add a label if we can confirm that a region was labelled. + let argument_index = self.get_argument_index_for_region(infcx.tcx, needle_fr)?; + let (_, span) = self.get_argument_name_and_span_for_region(mir, argument_index); + diag.span_label(span, format!("has type `{}`", type_name)); + + // This counter value will already have been used, so this function will increment it + // so the next value will be used next and return the region name that would have been + // used. + Some(self.synthesize_region_name(counter)) + } else { + None + }; + + assigned_region_name + } + /// Attempts to highlight the specific part of a type annotation /// that contains the anonymous reference we want to give a name /// to. For example, we might produce an annotation like this: diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr index 9c7e3db67a611..0ac295c54bccb 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr @@ -10,8 +10,8 @@ error: unsatisfied lifetime constraints LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 | ----------^^^^^----------------- | | | | - | | | free region requires that `'1` must outlive `'2` - | | lifetime `'1` appears in this argument + | | | requires that `'1` must outlive `'2` + | | has type `&'1 i32` | lifetime `'2` appears in return type error: aborting due to previous error diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index c6f8d2e519ca1..bbc63e6fecaf5 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -10,21 +10,19 @@ warning: not reporting region error due to nll LL | self.x.iter().map(|a| a.0) | ^^^^ -error: borrowed data escapes outside of closure +error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:17:9 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- `self` is a reference that is only valid in the closure body + | - let's call the lifetime of this reference `'1` LL | self.x.iter().map(|a| a.0) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here + | ^^^^^^^^^^^^^ requires that `'1` must outlive `'static` -error: borrowed data escapes outside of closure +error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:21:9 | -LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- `self` is a reference that is only valid in the closure body LL | self.x.iter().map(|a| a.0) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here + | ^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr index e26b1956d5e81..f5d98e04ad804 100644 --- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr @@ -4,13 +4,13 @@ warning: not reporting region error due to nll LL | static_val(x); //~ ERROR cannot infer | ^ -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/dyn-trait.rs:32:5 | LL | fn with_dyn_debug_static<'a>(x: Box) { - | - `x` is a reference that is only valid in the closure body + | - `x` is a reference that is only valid in the function body LL | static_val(x); //~ ERROR cannot infer - | ^^^^^^^^^^^^^ `x` escapes the closure body here + | ^^^^^^^^^^^^^ `x` escapes the function body here error: aborting due to previous error diff --git a/src/test/ui/issue-10291.nll.stderr b/src/test/ui/issue-10291.nll.stderr index 1358fe010b443..6de00ffd48cc1 100644 --- a/src/test/ui/issue-10291.nll.stderr +++ b/src/test/ui/issue-10291.nll.stderr @@ -8,7 +8,7 @@ error: unsatisfied lifetime constraints --> $DIR/issue-10291.rs:12:5 | LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ free region requires that `'x` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/issue-16683.nll.stderr b/src/test/ui/issue-16683.nll.stderr index f9dda27da0985..890bb426441e2 100644 --- a/src/test/ui/issue-16683.nll.stderr +++ b/src/test/ui/issue-16683.nll.stderr @@ -10,13 +10,13 @@ warning: not reporting region error due to nll LL | self.a(); //~ ERROR cannot infer | ^ -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/issue-16683.rs:14:9 | LL | fn b(&self) { - | ----- `self` is a reference that is only valid in the closure body + | ----- `self` is a reference that is only valid in the function body LL | self.a(); //~ ERROR cannot infer - | ^^^^^^^^ `self` escapes the closure body here + | ^^^^^^^^ `self` escapes the function body here error: aborting due to previous error diff --git a/src/test/ui/issue-17758.nll.stderr b/src/test/ui/issue-17758.nll.stderr index 5775135aefc5f..c51a72f885d6c 100644 --- a/src/test/ui/issue-17758.nll.stderr +++ b/src/test/ui/issue-17758.nll.stderr @@ -10,13 +10,13 @@ warning: not reporting region error due to nll LL | self.foo(); | ^^^ -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/issue-17758.rs:17:9 | LL | fn bar(&self) { - | ----- `self` is a reference that is only valid in the closure body + | ----- `self` is a reference that is only valid in the function body LL | self.foo(); - | ^^^^^^^^^^ `self` escapes the closure body here + | ^^^^^^^^^^ `self` escapes the function body here error: aborting due to previous error diff --git a/src/test/ui/issue-40510-1.nll.stderr b/src/test/ui/issue-40510-1.nll.stderr index 73a8d58290dfa..312ec6e742e91 100644 --- a/src/test/ui/issue-40510-1.nll.stderr +++ b/src/test/ui/issue-40510-1.nll.stderr @@ -6,7 +6,7 @@ LL | || { | |_____| | || LL | || &mut x - | || ^^^^^^ free region requires that `'1` must outlive `'2` + | || ^^^^^^ return requires that `'1` must outlive `'2` LL | || }; | || - | ||_____| diff --git a/src/test/ui/issue-40510-3.nll.stderr b/src/test/ui/issue-40510-3.nll.stderr index 4133c69f031a5..eb44850e639ab 100644 --- a/src/test/ui/issue-40510-3.nll.stderr +++ b/src/test/ui/issue-40510-3.nll.stderr @@ -9,7 +9,7 @@ LL | || || { | ||_________^ LL | ||| x.push(()) LL | ||| } - | |||_________^ free region requires that `'1` must outlive `'2` + | |||_________^ requires that `'1` must outlive `'2` LL | || }; | || - | ||_____| diff --git a/src/test/ui/issue-52213.nll.stderr b/src/test/ui/issue-52213.nll.stderr index c288cf9ed820c..7dd513d1b712c 100644 --- a/src/test/ui/issue-52213.nll.stderr +++ b/src/test/ui/issue-52213.nll.stderr @@ -8,7 +8,7 @@ error: unsatisfied lifetime constraints --> $DIR/issue-52213.rs:13:11 | LL | ((u,),) => u, - | ^ free region requires that `'a` must outlive `'b` + | ^ requires that `'a` must outlive `'b` error: aborting due to previous error diff --git a/src/test/ui/issue-52533-1.nll.stderr b/src/test/ui/issue-52533-1.nll.stderr new file mode 100644 index 0000000000000..87fda1dd99c2e --- /dev/null +++ b/src/test/ui/issue-52533-1.nll.stderr @@ -0,0 +1,17 @@ +warning: not reporting region error due to nll + --> $DIR/issue-52533-1.rs:19:18 + | +LL | gimme(|x, y| y) + | ^ + +error: unsatisfied lifetime constraints + --> $DIR/issue-52533-1.rs:19:18 + | +LL | gimme(|x, y| y) + | - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2` + | | | + | | has type `&Foo<'_, '1, u32>` + | has type `&Foo<'_, '2, u32>` + +error: aborting due to previous error + diff --git a/src/test/ui/issue-52533-1.rs b/src/test/ui/issue-52533-1.rs new file mode 100644 index 0000000000000..22af5a8670257 --- /dev/null +++ b/src/test/ui/issue-52533-1.rs @@ -0,0 +1,21 @@ +// 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. + +#![allow(warnings)] + +struct Foo<'a, 'b, T: 'a + 'b> { x: &'a T, y: &'b T } + +fn gimme(_: impl for<'a, 'b, 'c> FnOnce(&'a Foo<'a, 'b, u32>, + &'a Foo<'a, 'c, u32>) -> &'a Foo<'a, 'b, u32>) { } + +fn main() { + gimme(|x, y| y) + //~^ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/issue-52533-1.stderr b/src/test/ui/issue-52533-1.stderr new file mode 100644 index 0000000000000..38deb7d66de08 --- /dev/null +++ b/src/test/ui/issue-52533-1.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-52533-1.rs:19:18 + | +LL | gimme(|x, y| y) + | ^ lifetime mismatch + | + = note: expected type `&Foo<'_, '_, u32>` + found type `&Foo<'_, '_, u32>` +note: the anonymous lifetime #4 defined on the body at 19:11... + --> $DIR/issue-52533-1.rs:19:11 + | +LL | gimme(|x, y| y) + | ^^^^^^^^ +note: ...does not necessarily outlive the anonymous lifetime #3 defined on the body at 19:11 + --> $DIR/issue-52533-1.rs:19:11 + | +LL | gimme(|x, y| y) + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-52533.nll.stderr b/src/test/ui/issue-52533.nll.stderr new file mode 100644 index 0000000000000..a13b06e320483 --- /dev/null +++ b/src/test/ui/issue-52533.nll.stderr @@ -0,0 +1,17 @@ +warning: not reporting region error due to nll + --> $DIR/issue-52533.rs:15:16 + | +LL | foo(|a, b| b) + | ^ + +error: unsatisfied lifetime constraints + --> $DIR/issue-52533.rs:15:16 + | +LL | foo(|a, b| b) + | - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2` + | | | + | | has type `&'1 u32` + | has type `&'2 u32` + +error: aborting due to previous error + diff --git a/src/test/ui/issue-52533.rs b/src/test/ui/issue-52533.rs new file mode 100644 index 0000000000000..08f2805cefd6d --- /dev/null +++ b/src/test/ui/issue-52533.rs @@ -0,0 +1,17 @@ +// 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. + +fn foo(_: impl for<'a> FnOnce(&'a u32, &u32) -> &'a u32) { +} + +fn main() { + foo(|a, b| b) + //~^ ERROR lifetime of reference outlives lifetime of borrowed content... +} diff --git a/src/test/ui/issue-52533.stderr b/src/test/ui/issue-52533.stderr new file mode 100644 index 0000000000000..76a2470a2e03e --- /dev/null +++ b/src/test/ui/issue-52533.stderr @@ -0,0 +1,20 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/issue-52533.rs:15:16 + | +LL | foo(|a, b| b) + | ^ + | +note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 15:9... + --> $DIR/issue-52533.rs:15:9 + | +LL | foo(|a, b| b) + | ^^^^^^^^ +note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined on the body at 15:9 + --> $DIR/issue-52533.rs:15:9 + | +LL | foo(|a, b| b) + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0312`. diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index d6f542183603e..ccf116e640d42 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -8,10 +8,10 @@ error: unsatisfied lifetime constraints --> $DIR/escape-argument-callee.rs:36:45 | LL | let mut closure = expect_sig(|p, y| *p = y); - | - - ^^^^^^ free region requires that `'1` must outlive `'2` + | - - ^^^^^^ requires that `'1` must outlive `'2` | | | - | | lifetime `'1` appears in this argument - | lifetime `'2` appears in this argument + | | has type `&'1 i32` + | has type `&mut &'2 i32` note: No external requirements --> $DIR/escape-argument-callee.rs:36:38 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index a7a50a3a02981..b450882490195 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13 | LL | |_outlives1, _outlives2, _outlives3, x, y| { - | ---------- ---------- lifetime `'2` appears in this argument + | ---------- ---------- has type `std::cell::Cell<&'2 &u32>` | | - | lifetime `'1` appears in this argument + | has type `std::cell::Cell<&&'1 u32>` ... LL | demand_y(x, y, p) //~ ERROR | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 3177cd7c28f64..33e4240736f5b 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -23,18 +23,18 @@ LL | | }); = note: number of external vids: 2 = note: where '_#1r: '_#0r -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the closure body + | ------ `cell_a` is a reference that is only valid in the function body LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { LL | | //~^ ERROR LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll LL | | }); - | |______^ `cell_a` escapes the closure body here + | |______^ `cell_a` escapes the function body here note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 089c88abcdd4a..5f98a0fd36d79 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -23,18 +23,18 @@ LL | | }); = note: number of external vids: 3 = note: where '_#1r: '_#0r -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the closure body + | ------ `cell_a` is a reference that is only valid in the function body LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { LL | | //~^ ERROR LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | //~^ WARNING not reporting region error due to nll LL | | }); - | |______^ `cell_a` escapes the closure body here + | |______^ `cell_a` escapes the function body here note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1 diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index fb98c506c7d28..40ebda4419b2a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | --------- - lifetime `'1` appears in this argument + | --------- - has type `&std::cell::Cell<&'1 u32>` | | - | lifetime `'2` appears in this argument + | has type `&std::cell::Cell<&'2 &u32>` LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 73d39a8502b64..37ea610397696 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | ---------- ---------- lifetime `'2` appears in this argument + | ---------- ---------- has type `&std::cell::Cell<&'2 &u32>` | | - | lifetime `'1` appears in this argument + | has type `&std::cell::Cell<&'1 &u32>` LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr index d012dca25271c..b056271162738 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -8,7 +8,7 @@ error: unsatisfied lifetime constraints --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 | LL | &*x - | ^^^ free region requires that `'a` must outlive `'static` + | ^^^ requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 5724cdbd8c95b..d6d1645ceeacc 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -8,10 +8,10 @@ error: unsatisfied lifetime constraints --> $DIR/return-wrong-bound-region.rs:21:23 | LL | expect_sig(|a, b| b); // ought to return `a` - | - - ^ free region requires that `'1` must outlive `'2` + | - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2` | | | - | | lifetime `'1` appears in this argument - | lifetime `'2` appears in this argument + | | has type `&'1 i32` + | has type `&'2 i32` note: No external requirements --> $DIR/return-wrong-bound-region.rs:21:16 diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr index 8acf2ef51ecd2..f12ab9b4f9602 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.stderr @@ -1,11 +1,11 @@ -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/issue-50716.rs:25:14 | LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) - | - `s` is a reference that is only valid in the closure body + | - `s` is a reference that is only valid in the function body ... LL | let _x = *s; //~ ERROR - | ^^ `s` escapes the closure body here + | ^^ `s` escapes the function body here error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr index 13f90e1f159d2..d8f186a22324b 100644 --- a/src/test/ui/nll/mir_check_cast_reify.stderr +++ b/src/test/ui/nll/mir_check_cast_reify.stderr @@ -4,14 +4,14 @@ warning: not reporting region error due to nll LL | let f: fn(_) -> _ = foo; | ^^^ -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/mir_check_cast_reify.rs:48:5 | LL | fn bar<'a>(x: &'a u32) -> &'static u32 { - | - `x` is a reference that is only valid in the closure body + | - `x` is a reference that is only valid in the function body ... LL | f(x) - | ^^^^ `x` escapes the closure body here + | ^^^^ `x` escapes the function body here error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr index b08c6f32e6b43..98c03e378147a 100644 --- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr +++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr @@ -4,14 +4,14 @@ warning: not reporting region error due to nll LL | let g: unsafe fn(_) -> _ = f; | ^ -error: borrowed data escapes outside of closure +error: borrowed data escapes outside of function --> $DIR/mir_check_cast_unsafe_fn.rs:20:14 | LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { - | ----- `input` is a reference that is only valid in the closure body + | ----- `input` is a reference that is only valid in the function body ... LL | unsafe { g(input) } - | ^^^^^^^^ `input` escapes the closure body here + | ^^^^^^^^ `input` escapes the function body here error: aborting due to previous error