From f49ebbb891c2b6d3226bf77fd82c9cd22e389f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 24 May 2020 10:34:03 -0700 Subject: [PATCH 01/10] Account for missing lifetime in opaque return type When encountering an opaque closure return type that needs to bound a lifetime to the function's arguments, including borrows and type params, provide appropriate suggestions that lead to working code. Get the user from ```rust fn foo(g: G, dest: &mut T) -> impl FnOnce() where G: Get { move || { *dest = g.get(); } } ``` to ```rust fn foo<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() +'a where G: Get { move || { *dest = g.get(); } } ``` --- .../infer/error_reporting/mod.rs | 140 ++++++++++++----- .../nice_region_error/static_impl_trait.rs | 17 +- .../infer/error_reporting/note.rs | 25 ++- .../missing-lifetimes-in-signature.rs | 100 ++++++++++++ .../missing-lifetimes-in-signature.stderr | 146 ++++++++++++++++++ 5 files changed, 359 insertions(+), 69 deletions(-) create mode 100644 src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs create mode 100644 src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index ae901982817..3b98d47778f 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1682,49 +1682,70 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) -> DiagnosticBuilder<'a> { + let hir = &self.tcx.hir(); // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. - let type_param_span = match (self.in_progress_tables, bound_kind) { - (Some(ref table), GenericKind::Param(ref param)) => { - let table_owner = table.borrow().hir_owner; - table_owner.and_then(|table_owner| { - let generics = self.tcx.generics_of(table_owner.to_def_id()); - // Account for the case where `param` corresponds to `Self`, - // which doesn't have the expected type argument. - if !(generics.has_self && param.index == 0) { - let type_param = generics.type_param(param, self.tcx); - let hir = &self.tcx.hir(); - type_param.def_id.as_local().map(|def_id| { - // Get the `hir::Param` to verify whether it already has any bounds. - // We do this to avoid suggesting code that ends up as `T: 'a'b`, - // instead we suggest `T: 'a + 'b` in that case. - let id = hir.as_local_hir_id(def_id); - let mut has_bounds = false; - if let Node::GenericParam(param) = hir.get(id) { - has_bounds = !param.bounds.is_empty(); - } - let sp = hir.span(id); - // `sp` only covers `T`, change it so that it covers - // `T:` when appropriate - let is_impl_trait = bound_kind.to_string().starts_with("impl "); - let sp = if has_bounds && !is_impl_trait { - sp.to(self - .tcx - .sess - .source_map() - .next_point(self.tcx.sess.source_map().next_point(sp))) - } else { - sp - }; - (sp, has_bounds, is_impl_trait) - }) - } else { - None - } - }) + let generics = self + .in_progress_tables + .and_then(|table| table.borrow().hir_owner) + .map(|table_owner| self.tcx.generics_of(table_owner.to_def_id())); + let type_param_span = match (generics, bound_kind) { + (Some(ref generics), GenericKind::Param(ref param)) => { + // Account for the case where `param` corresponds to `Self`, + // which doesn't have the expected type argument. + if !(generics.has_self && param.index == 0) { + let type_param = generics.type_param(param, self.tcx); + type_param.def_id.as_local().map(|def_id| { + // Get the `hir::Param` to verify whether it already has any bounds. + // We do this to avoid suggesting code that ends up as `T: 'a'b`, + // instead we suggest `T: 'a + 'b` in that case. + let id = hir.as_local_hir_id(def_id); + let mut has_bounds = false; + if let Node::GenericParam(param) = hir.get(id) { + has_bounds = !param.bounds.is_empty(); + } + let sp = hir.span(id); + // `sp` only covers `T`, change it so that it covers + // `T:` when appropriate + let is_impl_trait = bound_kind.to_string().starts_with("impl "); + let sp = if has_bounds && !is_impl_trait { + sp.to(self + .tcx + .sess + .source_map() + .next_point(self.tcx.sess.source_map().next_point(sp))) + } else { + sp + }; + (sp, has_bounds, is_impl_trait) + }) + } else { + None + } } _ => None, }; + let new_lt = generics + .as_ref() + .and_then(|g| { + let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"]; + let lts_names = g + .params + .iter() + .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) + .map(|p| p.name.as_str()) + .collect::>(); + let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); + possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s) + }) + .unwrap_or("'lt"); + let add_lt_sugg = generics + .as_ref() + .and_then(|g| g.params.first()) + .and_then(|param| param.def_id.as_local()) + .map(|def_id| { + (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt)) + }); let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{}`", p), @@ -1781,6 +1802,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + let new_binding_suggestion = + |err: &mut DiagnosticBuilder<'tcx>, + type_param_span: Option<(Span, bool, bool)>, + bound_kind: GenericKind<'tcx>| { + let msg = "consider introducing an explicit lifetime bound to unify the type \ + parameter and the output"; + if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span { + let suggestion = if is_impl_trait { + (sp.shrink_to_hi(), format!(" + {}", new_lt)) + } else { + let tail = if has_lifetimes { " +" } else { "" }; + (sp, format!("{}: {}{}", bound_kind, new_lt, tail)) + }; + let mut sugg = + vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))]; + if let Some(lt) = add_lt_sugg { + sugg.push(lt); + sugg.rotate_right(1); + } + // `MaybeIncorrect` due to issue #41966. + err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect); + } + }; + let mut err = match *sub { ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. }) | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }) => { @@ -1822,10 +1867,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "{} may not live long enough", labeled_user_string ); - err.help(&format!( - "consider adding an explicit lifetime bound for `{}`", - bound_kind - )); note_and_explain_region( self.tcx, &mut err, @@ -1833,6 +1874,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sub, "...", ); + if let Some(infer::RelateParamBound(_, t)) = origin { + let t = self.resolve_vars_if_possible(&t); + match t.kind { + // We've got: + // fn get_later(g: G, dest: &mut T) -> impl FnOnce() + '_ + // suggest: + // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + ty::Closure(_, _substs) | ty::Opaque(_, _substs) => { + new_binding_suggestion(&mut err, type_param_span, bound_kind); + } + _ => { + binding_suggestion(&mut err, type_param_span, bound_kind, new_lt); + } + } + } err } }; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 7f3ec852e41..4ad587db012 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -4,7 +4,7 @@ use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use rustc_errors::{Applicability, ErrorReported}; -use rustc_middle::ty::{BoundRegion, FreeRegion, RegionKind}; +use rustc_middle::ty::RegionKind; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. @@ -37,13 +37,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_note(lifetime_sp, &format!("...can't outlive {}", lifetime)); } - let lifetime_name = match sup_r { - RegionKind::ReFree(FreeRegion { - bound_region: BoundRegion::BrNamed(_, ref name), - .. - }) => name.to_string(), - _ => "'_".to_owned(), - }; + let lifetime_name = + if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; let fn_return_span = return_ty.unwrap().1; if let Ok(snippet) = self.tcx().sess.source_map().span_to_snippet(fn_return_span) @@ -54,9 +49,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_suggestion( fn_return_span, &format!( - "you can add a bound to the return type to make it last \ - less than `'static` and match {}", - lifetime, + "you can add a bound to the return type to make it last less \ + than `'static` and match {}", + lifetime ), format!("{} + {}", snippet, lifetime_name), Applicability::Unspecified, diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs index 8fbb89da5af..968c488bc00 100644 --- a/src/librustc_infer/infer/error_reporting/note.rs +++ b/src/librustc_infer/infer/error_reporting/note.rs @@ -56,8 +56,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_note( span, &format!( - "...so that the reference type `{}` does not outlive the \ - data it points at", + "...so that the reference type `{}` does not outlive the data it points at", self.ty_to_string(ty) ), ); @@ -66,8 +65,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_note( span, &format!( - "...so that the type `{}` will meet its required \ - lifetime bounds", + "...so that the type `{}` will meet its required lifetime bounds", self.ty_to_string(t) ), ); @@ -81,8 +79,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::CompareImplMethodObligation { span, .. } => { err.span_note( span, - "...so that the definition in impl matches the definition from the \ - trait", + "...so that the definition in impl matches the definition from the trait", ); } } @@ -113,8 +110,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0312, - "lifetime of reference outlives lifetime of \ - borrowed content..." + "lifetime of reference outlives lifetime of borrowed content..." ); note_and_explain_region( self.tcx, @@ -138,8 +134,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0313, - "lifetime of borrowed pointer outlives lifetime \ - of captured variable `{}`...", + "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", var_name ); note_and_explain_region( @@ -163,8 +158,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0476, - "lifetime of the source pointer does not outlive \ - lifetime bound of the object type" + "lifetime of the source pointer does not outlive lifetime bound of the \ + object type" ); note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, ""); note_and_explain_region( @@ -181,8 +176,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0477, - "the type `{}` does not fulfill the required \ - lifetime", + "the type `{}` does not fulfill the required lifetime", self.ty_to_string(ty) ); match *sub { @@ -217,8 +211,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0482, - "lifetime of return value does not outlive the \ - function call" + "lifetime of return value does not outlive the function call" ); note_and_explain_region( self.tcx, diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs new file mode 100644 index 00000000000..b5f6fdeaa4e --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -0,0 +1,100 @@ +pub trait Get { + fn get(self) -> T; +} + +struct Foo { + x: usize, +} + +impl Get for Foo { + fn get(self) -> usize { + self.x + } +} + +fn foo(g: G, dest: &mut T) -> impl FnOnce() +where + G: Get +{ + move || { //~ ERROR cannot infer an appropriate lifetime + *dest = g.get(); + } +} + +// After applying suggestion for `foo`: +fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +//~^ ERROR the parameter type `G` may not live long enough +where + G: Get +{ + move || { + *dest = g.get(); + } +} + + +// After applying suggestion for `bar`: +fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared lifetime +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// After applying suggestion for `baz`: +fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +//~^ ERROR the parameter type `G` may not live long enough +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// After applying suggestion for `qux`: +// FIXME: we should suggest be suggesting to change `dest` to `&'a mut T`. +fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +where + G: Get +{ + move || { //~ ERROR cannot infer an appropriate lifetime + *dest = g.get(); + } +} + +// Potential incorrect attempt: +fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +//~^ ERROR the parameter type `G` may not live long enough +where + G: Get +{ + move || { + *dest = g.get(); + } +} + + +// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure: +fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: +fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr new file mode 100644 index 00000000000..d69db90f3ba --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -0,0 +1,146 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetimes-in-signature.rs:37:11 + | +LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error: cannot infer an appropriate lifetime + --> $DIR/missing-lifetimes-in-signature.rs:19:5 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | ------------- this return type evaluates to the `'static` lifetime... +... +LL | / move || { +LL | | *dest = g.get(); +LL | | } + | |_____^ ...but this borrow... + | +note: ...can't outlive the anonymous lifetime #1 defined on the function body at 15:1 + --> $DIR/missing-lifetimes-in-signature.rs:15:1 + | +LL | / fn foo(g: G, dest: &mut T) -> impl FnOnce() +LL | | where +LL | | G: Get +LL | | { +... | +LL | | } +LL | | } + | |_^ +help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 15:1 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:25:37 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 25:1... + --> $DIR/missing-lifetimes-in-signature.rs:25:1 + | +LL | / fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:25:37 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime bound to unify the type parameter and the output + | +LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^ ^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:47:45 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 47:1... + --> $DIR/missing-lifetimes-in-signature.rs:47:1 + | +LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:47:45 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime bound to unify the type parameter and the output + | +LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b + | ^^^ ^^^^^^^ ^^^^ + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/missing-lifetimes-in-signature.rs:63:5 + | +LL | / move || { +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 59:1... + --> $DIR/missing-lifetimes-in-signature.rs:59:1 + | +LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +LL | | where +LL | | G: Get +LL | | { +... | +LL | | } +LL | | } + | |_^ +note: ...so that the types are compatible + --> $DIR/missing-lifetimes-in-signature.rs:63:5 + | +LL | / move || { +LL | | *dest = g.get(); +LL | | } + | |_____^ + = note: expected `&mut T` + found `&mut T` +note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 59:8... + --> $DIR/missing-lifetimes-in-signature.rs:59:8 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^ +note: ...so that return value is valid for the call + --> $DIR/missing-lifetimes-in-signature.rs:59:45 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0309]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:69:44 + | +LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + | - ^^^^^^^^^^^^^^^^^^ + | | + | help: consider adding an explicit lifetime bound...: `G: 'a` + | +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:74:5: 76:6 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:69:44 + | +LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0261, E0309, E0495. +For more information about an error, try `rustc --explain E0261`. From 99d9ccd5478c1cdfbe96216a59e3ce5b2e936278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 24 May 2020 11:52:12 -0700 Subject: [PATCH 02/10] Improve output of argument anonymous borrow missing annotation involving opaque return type Go from ``` error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> file8.rs:22:5 | 22 | / move || { 23 | | *dest = g.get(); 24 | | } | |_____^ | note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 18:1... --> file8.rs:18:1 | 18 | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a 19 | | where 20 | | G: Get 21 | | { ... | 24 | | } 25 | | } | |_^ note: ...so that the types are compatible --> file8.rs:22:5 | 22 | / move || { //~ ERROR cannot infer an appropriate lifetime 23 | | *dest = g.get(); 24 | | } | |_____^ = note: expected `&mut T` found `&mut T` note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 18:8... --> file8.rs:18:8 | 18 | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ^^ note: ...so that return value is valid for the call --> file8.rs:18:45 | 18 | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ^^^^^^^^^^^^^^^^^^^^^^^ ``` to ``` error[E0621]: explicit lifetime required in the type of `dest` --> file8.rs:18:45 | 18 | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required | | | help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` ``` --- .../infer/error_reporting/mod.rs | 11 ++--- .../nice_region_error/named_anon_conflict.rs | 15 +++++-- .../missing-lifetimes-in-signature.rs | 4 +- .../missing-lifetimes-in-signature.stderr | 43 +++---------------- .../dyn-trait-underscore.nll.stderr | 7 +-- .../dyn-trait-underscore.rs | 2 +- .../dyn-trait-underscore.stderr | 31 +++---------- 7 files changed, 37 insertions(+), 76 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 3b98d47778f..a7b40d39215 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1917,14 +1917,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "...", ); + debug!("report_sub_sup_conflict: var_origin={:?}", var_origin); + debug!("report_sub_sup_conflict: sub_region={:?}", sub_region); + debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin); + debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); + debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); + if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { - debug!("report_sub_sup_conflict: var_origin={:?}", var_origin); - debug!("report_sub_sup_conflict: sub_region={:?}", sub_region); - debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin); - debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); - debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace); debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace); debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values); diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs index b85a4cae2e4..9da24138eeb 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -74,13 +74,22 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let Some((_, fndecl)) = self.find_anon_type(anon, &br) { - if self.is_return_type_anon(scope_def_id, br, fndecl).is_some() - || self.is_self_anon(is_first, scope_def_id) - { + let return_type_anon = self.is_return_type_anon(scope_def_id, br, fndecl); + let is_self_anon = self.is_self_anon(is_first, scope_def_id); + debug!( + "try_report_named_anon_conflict: fndecl {:?} {:?} {}", + fndecl, return_type_anon, is_self_anon + ); + if is_self_anon { + // We used to check for `return_type_anon.is_some()` here. Removing that improves + // some diagnostics, but we might have to readd the check if there are regressions + // in the wild. return None; } if let FnRetTy::Return(ty) = &fndecl.output { + debug!("try_report_named_anon_conflict: ret ty {:?}", ty); if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.kind, sub) { + debug!("try_report_named_anon_conflict: impl Trait + 'static"); // This is an impl Trait return that evaluates de need of 'static. // We handle this case better in `static_impl_trait`. return None; diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index b5f6fdeaa4e..589d04c9b19 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -55,12 +55,12 @@ where } // After applying suggestion for `qux`: -// FIXME: we should suggest be suggesting to change `dest` to `&'a mut T`. fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +//~^ ERROR explicit lifetime required in the type of `dest` where G: Get { - move || { //~ ERROR cannot infer an appropriate lifetime + move || { *dest = g.get(); } } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index d69db90f3ba..0326616337d 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -87,44 +87,13 @@ help: consider introducing an explicit lifetime bound to unify the type paramete LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b | ^^^ ^^^^^^^ ^^^^ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/missing-lifetimes-in-signature.rs:63:5 - | -LL | / move || { -LL | | *dest = g.get(); -LL | | } - | |_____^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 59:1... - --> $DIR/missing-lifetimes-in-signature.rs:59:1 - | -LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a -LL | | where -LL | | G: Get -LL | | { -... | -LL | | } -LL | | } - | |_^ -note: ...so that the types are compatible - --> $DIR/missing-lifetimes-in-signature.rs:63:5 - | -LL | / move || { -LL | | *dest = g.get(); -LL | | } - | |_____^ - = note: expected `&mut T` - found `&mut T` -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 59:8... - --> $DIR/missing-lifetimes-in-signature.rs:59:8 +error[E0621]: explicit lifetime required in the type of `dest` + --> $DIR/missing-lifetimes-in-signature.rs:58:45 | LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ^^ -note: ...so that return value is valid for the call - --> $DIR/missing-lifetimes-in-signature.rs:59:45 - | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` error[E0309]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:69:44 @@ -142,5 +111,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a error: aborting due to 6 previous errors -Some errors have detailed explanations: E0261, E0309, E0495. +Some errors have detailed explanations: E0261, E0309, E0621. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 8ed48bda26e..a1f6c5386ae 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -1,11 +1,12 @@ -error: lifetime may not live long enough +error[E0621]: explicit lifetime required in the type of `items` --> $DIR/dyn-trait-underscore.rs:8:5 | LL | fn a(items: &[T]) -> Box> { - | - let's call the lifetime of this reference `'1` + | ---- help: add explicit lifetime `'static` to the type of `items`: `&'static [T]` LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required error: aborting due to previous error +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs index d5aa18eb0f4..cd4781b8640 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -5,7 +5,7 @@ fn a(items: &[T]) -> Box> { // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` - Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + Box::new(items.iter()) //~ ERROR explicit lifetime required in the type of `items` } fn b(items: &[T]) -> Box + '_> { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index e3c9d50dfe5..a1f6c5386ae 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,31 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements - --> $DIR/dyn-trait-underscore.rs:8:20 - | -LL | Box::new(items.iter()) - | ^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 6:1... - --> $DIR/dyn-trait-underscore.rs:6:1 - | -LL | / fn a(items: &[T]) -> Box> { -LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` -LL | | Box::new(items.iter()) -LL | | } - | |_^ -note: ...so that reference does not outlive borrowed content - --> $DIR/dyn-trait-underscore.rs:8:14 - | -LL | Box::new(items.iter()) - | ^^^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +error[E0621]: explicit lifetime required in the type of `items` --> $DIR/dyn-trait-underscore.rs:8:5 | +LL | fn a(items: &[T]) -> Box> { + | ---- help: add explicit lifetime `'static` to the type of `items`: `&'static [T]` +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn std::iter::Iterator + 'static)>` - found `std::boxed::Box>` + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0621`. From a724d9a4fb1abade3754ffcd2c92bb755b7d5ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 24 May 2020 12:00:40 -0700 Subject: [PATCH 03/10] Fix NLL output --- .../missing-lifetimes-in-signature.nll.stderr | 98 +++++++++++++++++++ .../dyn-trait-underscore.nll.stderr | 12 --- 2 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr delete mode 100644 src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr new file mode 100644 index 00000000000..f11c978aabf --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr @@ -0,0 +1,98 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetimes-in-signature.rs:37:11 + | +LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error: lifetime may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:15:37 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | - ^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:25:37 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 25:1... + --> $DIR/missing-lifetimes-in-signature.rs:25:1 + | +LL | / fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:47:45 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 47:1... + --> $DIR/missing-lifetimes-in-signature.rs:47:1 + | +LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:58:45 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 58:1... + --> $DIR/missing-lifetimes-in-signature.rs:58:1 + | +LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ + +error[E0621]: explicit lifetime required in the type of `dest` + --> $DIR/missing-lifetimes-in-signature.rs:63:5 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` +... +LL | / move || { +LL | | *dest = g.get(); +LL | | } + | |_____^ lifetime `'a` required + +error[E0309]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:69:44 + | +LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `G: 'a`... + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0261, E0309, E0621. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr deleted file mode 100644 index a1f6c5386ae..00000000000 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0621]: explicit lifetime required in the type of `items` - --> $DIR/dyn-trait-underscore.rs:8:5 - | -LL | fn a(items: &[T]) -> Box> { - | ---- help: add explicit lifetime `'static` to the type of `items`: `&'static [T]` -LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` -LL | Box::new(items.iter()) - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0621`. From 65f492be121ee9901d8c4305629cf4f2ad88f6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 26 May 2020 13:13:19 -0700 Subject: [PATCH 04/10] Account for returned `dyn Trait` evaluating to `'static` lifetime Provide a suggestion for `dyn Trait + '_` when possible. --- .../error_reporting/nice_region_error/mod.rs | 2 +- .../nice_region_error/named_anon_conflict.rs | 38 ++----- .../nice_region_error/static_impl_trait.rs | 44 ++++---- src/librustc_middle/ty/context.rs | 101 +++++++++++++----- src/librustc_middle/ty/diagnostics.rs | 19 ++++ .../ui/async-await/issues/issue-62097.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 18 ++-- .../static-return-lifetime-infered.stderr | 12 +-- src/test/ui/issues/issue-16922.rs | 2 +- src/test/ui/issues/issue-16922.stderr | 25 +++-- .../object-lifetime-default-from-box-error.rs | 2 +- ...ect-lifetime-default-from-box-error.stderr | 25 ++++- .../region-object-lifetime-in-coercion.rs | 9 +- .../region-object-lifetime-in-coercion.stderr | 40 ++++--- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 6 +- .../missing-lifetimes-in-signature.stderr | 6 +- .../dyn-trait-underscore.rs | 2 +- .../dyn-trait-underscore.stderr | 26 +++-- 19 files changed, 239 insertions(+), 142 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs index efe52689550..cc8f1816bc3 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs @@ -55,9 +55,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { diag.emit(); ErrorReported }) + .or_else(|| self.try_report_impl_not_conforming_to_trait()) .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_static_impl_trait()) - .or_else(|| self.try_report_impl_not_conforming_to_trait()) } pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 9da24138eeb..acaf4746992 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -21,8 +21,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // where the anonymous region appears (there must always be one; we // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced - // with the named one.//scope_def_id - let (named, anon, anon_param_info, region_info) = if self.is_named_region(sub) + // with the named one. + let (named, anon, anon_param_info, region_info) = if sub.has_name() && self.tcx().is_suitable_region(sup).is_some() && self.find_param_with_region(sup, sub).is_some() { @@ -32,7 +32,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { self.find_param_with_region(sup, sub).unwrap(), self.tcx().is_suitable_region(sup).unwrap(), ) - } else if self.is_named_region(sup) + } else if sup.has_name() && self.tcx().is_suitable_region(sub).is_some() && self.find_param_with_region(sub, sup).is_some() { @@ -74,24 +74,21 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let Some((_, fndecl)) = self.find_anon_type(anon, &br) { - let return_type_anon = self.is_return_type_anon(scope_def_id, br, fndecl); let is_self_anon = self.is_self_anon(is_first, scope_def_id); - debug!( - "try_report_named_anon_conflict: fndecl {:?} {:?} {}", - fndecl, return_type_anon, is_self_anon - ); if is_self_anon { - // We used to check for `return_type_anon.is_some()` here. Removing that improves - // some diagnostics, but we might have to readd the check if there are regressions - // in the wild. return None; } + if let FnRetTy::Return(ty) = &fndecl.output { + let mut v = ty::TraitObjectVisitor(vec![]); + rustc_hir::intravisit::walk_ty(&mut v, ty); + debug!("try_report_named_anon_conflict: ret ty {:?}", ty); - if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.kind, sub) { + if sub == &ty::ReStatic && (matches!(ty.kind, TyKind::Def(_, _)) || v.0.len() == 1) + { debug!("try_report_named_anon_conflict: impl Trait + 'static"); - // This is an impl Trait return that evaluates de need of 'static. - // We handle this case better in `static_impl_trait`. + // This is an `impl Trait` or `dyn Trait` return that evaluates de need of + // `'static`. We handle this case better in `static_impl_trait`. return None; } } @@ -123,17 +120,4 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Some(diag) } - - // This method returns whether the given Region is Named - pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool { - match *region { - ty::ReStatic => true, - ty::ReFree(ref free_region) => match free_region.bound_region { - ty::BrNamed(..) => true, - _ => false, - }, - ty::ReEarlyBound(ebr) => ebr.has_name(), - _ => false, - } - } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 4ad587db012..1a8b7fda179 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -20,16 +20,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = error.clone() { let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; - let return_ty = self.tcx().return_type_impl_trait(anon_reg_sup.def_id); - if sub_r == &RegionKind::ReStatic && return_ty.is_some() { + let (fn_return_span, is_dyn) = + self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; + if sub_r == &RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - err.span_label( - return_sp, - "this return type evaluates to the `'static` lifetime...", - ); + err.span_label(return_sp, "this evaluates to the `'static` lifetime..."); err.span_label(sup_origin.span(), "...but this borrow..."); let (lifetime, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r); @@ -39,24 +37,22 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; - let fn_return_span = return_ty.unwrap().1; - if let Ok(snippet) = - self.tcx().sess.source_map().span_to_snippet(fn_return_span) - { - // only apply this suggestion onto functions with - // explicit non-desugar'able return. - if fn_return_span.desugaring_kind().is_none() { - err.span_suggestion( - fn_return_span, - &format!( - "you can add a bound to the return type to make it last less \ - than `'static` and match {}", - lifetime - ), - format!("{} + {}", snippet, lifetime_name), - Applicability::Unspecified, - ); - } + // only apply this suggestion onto functions with + // explicit non-desugar'able return. + if fn_return_span.desugaring_kind().is_none() { + let msg = format!( + "you can add a bound to the returned `{} Trait` to make it last less \ + than `'static` and match {}", + if is_dyn { "dyn" } else { "impl" }, + lifetime + ); + // FIXME: account for the need of parens in `&(dyn Trait + '_)` + err.span_suggestion_verbose( + fn_return_span.shrink_to_hi(), + &msg, + format!(" + {}", lifetime_name), + Applicability::MaybeIncorrect, + ); } err.emit(); return Some(ErrorReported); diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 3a08d202ea3..c9d240a5da9 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1,38 +1,27 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::DepGraph; -use crate::dep_graph::{self, DepConstructor}; +use crate::dep_graph::{self, DepConstructor, DepGraph}; use crate::hir::exports::Export; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; -use crate::lint::LintDiagnosticBuilder; -use crate::lint::{struct_lint_level, LintSource}; +use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintSource}; use crate::middle; -use crate::middle::cstore::CrateStoreDyn; -use crate::middle::cstore::EncodedMetadata; +use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata}; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::interpret::{Allocation, ConstValue, Scalar}; -use crate::mir::{interpret, Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; +use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::traits; -use crate::ty::query; use crate::ty::steal::Steal; -use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; -use crate::ty::subst::{GenericArgKind, UserSubsts}; -use crate::ty::CanonicalPolyFnSig; -use crate::ty::GenericParamDefKind; -use crate::ty::RegionKind; -use crate::ty::ReprOptions; +use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts}; use crate::ty::TyKind::*; -use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; -use crate::ty::{AdtDef, AdtKind, Const, Region}; -use crate::ty::{BindingMode, BoundVar}; -use crate::ty::{ConstVid, FloatVar, FloatVid, IntVar, IntVid, TyVar, TyVid}; -use crate::ty::{ExistentialPredicate, Predicate, PredicateKind}; -use crate::ty::{InferConst, ParamConst}; -use crate::ty::{InferTy, ParamTy, PolyFnSig, ProjectionTy}; -use crate::ty::{List, TyKind, TyS}; +use crate::ty::{ + self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, + DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, + IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, ProjectionTy, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, +}; use rustc_ast::ast; use rustc_ast::expand::allocator::AllocatorKind; use rustc_attr as attr; @@ -48,10 +37,8 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathHash, Definitions}; -use rustc_hir::lang_items; -use rustc_hir::lang_items::PanicLocationLangItem; -use rustc_hir::{HirId, Node, TraitCandidate}; -use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet}; +use rustc_hir::lang_items::{self, PanicLocationLangItem}; +use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; @@ -1396,6 +1383,66 @@ impl<'tcx> TyCtxt<'tcx> { }) } + pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> { + let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); + let hir_output = match self.hir().get(hir_id) { + Node::Item(hir::Item { + kind: + ItemKind::Fn( + hir::FnSig { + decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, + .. + }, + .., + ), + .. + }) + | Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, + .. + }, + _, + ), + .. + }) + | Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { + decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, + .. + }, + _, + ), + .. + }) => ty, + _ => return None, + }; + + let ret_ty = self.type_of(scope_def_id); + match ret_ty.kind { + ty::FnDef(_, _) => { + let sig = ret_ty.fn_sig(*self); + let output = self.erase_late_bound_regions(&sig.output()); + if output.is_impl_trait() { + let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); + Some((fn_decl.output.span(), false)) + } else { + let mut v = TraitObjectVisitor(vec![]); + rustc_hir::intravisit::walk_ty(&mut v, hir_output); + if v.0.len() == 1 { + return Some((v.0[0], true)); + } + None + } + } + _ => None, + } + } + pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> { // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 613d66d59c5..1403efb745b 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -249,3 +249,22 @@ pub fn suggest_constraining_type_param( true } } + +pub struct TraitObjectVisitor(pub Vec); +impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor { + type Map = rustc_hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + if let hir::TyKind::TraitObject( + _, + hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. }, + ) = ty.kind + { + self.0.push(ty.span); + } + } +} diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 94afccc06a9..cd141b82e41 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | pub async fn run_dummy_fn(&self) { | ^^^^^ ...but this borrow... LL | foo(|| self.bar()).await; - | --- this return type evaluates to the `'static` lifetime... + | --- this evaluates to the `'static` lifetime... | note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31 --> $DIR/issue-62097.rs:12:31 diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index cffa5ee8f14..42667d6ca1a 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -4,17 +4,17 @@ error: cannot infer an appropriate lifetime LL | fn elided(x: &i32) -> impl Copy { x } | --------- ^ ...but this borrow... | | - | this return type evaluates to the `'static` lifetime... + | this evaluates to the `'static` lifetime... | note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 --> $DIR/must_outlive_least_region_or_bound.rs:3:1 | LL | fn elided(x: &i32) -> impl Copy { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1 | LL | fn elided(x: &i32) -> impl Copy + '_ { x } - | ^^^^^^^^^^^^^^ + | ^^^^ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 @@ -22,17 +22,17 @@ error: cannot infer an appropriate lifetime LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | --------- ^ ...but this borrow... | | - | this return type evaluates to the `'static` lifetime... + | this evaluates to the `'static` lifetime... | note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13 --> $DIR/must_outlive_least_region_or_bound.rs:6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ^^ -help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } - | ^^^^^^^^^^^^^^ + | ^^^^ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:69 @@ -40,17 +40,17 @@ error: cannot infer an appropriate lifetime LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -------------------------------- ^ ...but this borrow... | | - | this return type evaluates to the `'static` lifetime... + | this evaluates to the `'static` lifetime... | note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15 --> $DIR/must_outlive_least_region_or_bound.rs:12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^ -help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error[E0623]: lifetime mismatch --> $DIR/must_outlive_least_region_or_bound.rs:17:61 diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index e550be19174..963de2d448d 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----------------------- this return type evaluates to the `'static` lifetime... + | ----------------------- this evaluates to the `'static` lifetime... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | @@ -15,16 +15,16 @@ LL | / fn iter_values_anon(&self) -> impl Iterator { LL | | self.x.iter().map(|a| a.0) LL | | } | |_____^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | ----------------------- this return type evaluates to the `'static` lifetime... + | ----------------------- this evaluates to the `'static` lifetime... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | @@ -35,10 +35,10 @@ note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | ^^ -help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs index 10a5cccbcee..827163ef83c 100644 --- a/src/test/ui/issues/issue-16922.rs +++ b/src/test/ui/issues/issue-16922.rs @@ -2,7 +2,7 @@ use std::any::Any; fn foo(value: &T) -> Box { Box::new(value) as Box - //~^ ERROR explicit lifetime required in the type of `value` [E0621] + //~^ ERROR cannot infer an appropriate lifetime } fn main() { diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 4e3d3ecb9c0..8bcfe979ce1 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,11 +1,24 @@ -error[E0621]: explicit lifetime required in the type of `value` - --> $DIR/issue-16922.rs:4:5 +error: cannot infer an appropriate lifetime + --> $DIR/issue-16922.rs:4:14 | -LL | fn foo(value: &T) -> Box { - | -- help: add explicit lifetime `'static` to the type of `value`: `&'static T` LL | Box::new(value) as Box - | ^^^^^^^^^^^^^^^ lifetime `'static` required + | ---------^^^^^- + | | | + | | ...but this borrow... + | this evaluates to the `'static` lifetime... + | +note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 + --> $DIR/issue-16922.rs:3:1 + | +LL | / fn foo(value: &T) -> Box { +LL | | Box::new(value) as Box +LL | | +LL | | } + | |_^ +help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1 + | +LL | fn foo(value: &T) -> Box { + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs index 587aab1edce..708ab1cf382 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs @@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box { // `Box` defaults to a `'static` bound, so this return // is illegal. - ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621] + ss.r //~ ERROR cannot infer an appropriate lifetime } fn store(ss: &mut SomeStruct, b: Box) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 78e4bdd374d..7981d082c80 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,11 +1,26 @@ -error[E0621]: explicit lifetime required in the type of `ss` +error: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | -LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>` -... LL | ss.r - | ^^^^ lifetime `'static` required + | ^^^^ + | | + | this evaluates to the `'static` lifetime... + | ...but this borrow... + | +note: ...can't outlive the anonymous lifetime #2 defined on the function body at 14:1 + --> $DIR/object-lifetime-default-from-box-error.rs:14:1 + | +LL | / fn load(ss: &mut SomeStruct) -> Box { +LL | | // `Box` defaults to a `'static` bound, so this return +LL | | // is illegal. +LL | | +LL | | ss.r +LL | | } + | |_^ +help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #2 defined on the function body at 14:1 + | +LL | fn load(ss: &mut SomeStruct) -> Box { + | ^^^^ error[E0621]: explicit lifetime required in the type of `ss` --> $DIR/object-lifetime-default-from-box-error.rs:31:12 diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs index 2dc67599913..d56eaf77b66 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs @@ -11,20 +11,17 @@ fn a(v: &[u8]) -> Box { } fn b(v: &[u8]) -> Box { - Box::new(v) - //~^ ERROR explicit lifetime required in the type of `v` [E0621] + Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621] } fn c(v: &[u8]) -> Box { // same as previous case due to RFC 599 - Box::new(v) - //~^ ERROR explicit lifetime required in the type of `v` [E0621] + Box::new(v) //~ ERROR cannot infer an appropriate lifetime } fn d<'a,'b>(v: &'a [u8]) -> Box { - Box::new(v) - //~^ ERROR cannot infer an appropriate lifetime due to conflicting + Box::new(v) //~ ERROR cannot infer an appropriate lifetime due to conflicting } fn e<'a:'b,'b>(v: &'a [u8]) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 069b897603c..8048b79b015 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -14,40 +14,54 @@ LL | fn b(v: &[u8]) -> Box { LL | Box::new(v) | ^^^^^^^^^^^ lifetime `'static` required -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:21:5 +error: cannot infer an appropriate lifetime + --> $DIR/region-object-lifetime-in-coercion.rs:20:14 | -LL | fn c(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` -... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ---------^- + | | | + | | ...but this borrow... + | this evaluates to the `'static` lifetime... + | +note: ...can't outlive the anonymous lifetime #1 defined on the function body at 17:1 + --> $DIR/region-object-lifetime-in-coercion.rs:17:1 + | +LL | / fn c(v: &[u8]) -> Box { +LL | | // same as previous case due to RFC 599 +LL | | +LL | | Box::new(v) +LL | | } + | |_^ +help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 17:1 + | +LL | fn c(v: &[u8]) -> Box { + | ^^^^ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/region-object-lifetime-in-coercion.rs:26:14 + --> $DIR/region-object-lifetime-in-coercion.rs:24:14 | LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 25:6... - --> $DIR/region-object-lifetime-in-coercion.rs:25:6 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6... + --> $DIR/region-object-lifetime-in-coercion.rs:23:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:26:14 + --> $DIR/region-object-lifetime-in-coercion.rs:24:14 | LL | Box::new(v) | ^ = note: expected `&[u8]` found `&'a [u8]` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9... - --> $DIR/region-object-lifetime-in-coercion.rs:25:9 +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9... + --> $DIR/region-object-lifetime-in-coercion.rs:23:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:26:5 + --> $DIR/region-object-lifetime-in-coercion.rs:24:5 | LL | Box::new(v) | ^^^^^^^^^^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 91075ffbdb6..fcde3bb5ca6 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- this return type evaluates to the `'static` lifetime... + | ^^^^ ---------- this evaluates to the `'static` lifetime... | | | ...but this borrow... | diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 47ab6fff838..c89ee27aa8c 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -4,17 +4,17 @@ error: cannot infer an appropriate lifetime LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ^^^^ ...but this borrow... | | - | this return type evaluates to the `'static` lifetime... + | this evaluates to the `'static` lifetime... | note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:5 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 0326616337d..5a2530bdcbb 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,7 +10,7 @@ error: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------------- this return type evaluates to the `'static` lifetime... + | ------------- this evaluates to the `'static` lifetime... ... LL | / move || { LL | | *dest = g.get(); @@ -28,10 +28,10 @@ LL | | { LL | | } LL | | } | |_^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 15:1 +help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 15:1 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ + | ^^^^ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:25:37 diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs index cd4781b8640..d5aa18eb0f4 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -5,7 +5,7 @@ fn a(items: &[T]) -> Box> { // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` - Box::new(items.iter()) //~ ERROR explicit lifetime required in the type of `items` + Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime } fn b(items: &[T]) -> Box + '_> { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index a1f6c5386ae..65714d16a81 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,12 +1,24 @@ -error[E0621]: explicit lifetime required in the type of `items` - --> $DIR/dyn-trait-underscore.rs:8:5 +error: cannot infer an appropriate lifetime + --> $DIR/dyn-trait-underscore.rs:8:20 | -LL | fn a(items: &[T]) -> Box> { - | ---- help: add explicit lifetime `'static` to the type of `items`: `&'static [T]` -LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required + | ---------------^^^^--- + | | | + | | ...but this borrow... + | this evaluates to the `'static` lifetime... + | +note: ...can't outlive the anonymous lifetime #1 defined on the function body at 6:1 + --> $DIR/dyn-trait-underscore.rs:6:1 + | +LL | / fn a(items: &[T]) -> Box> { +LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | | Box::new(items.iter()) +LL | | } + | |_^ +help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 6:1 + | +LL | fn a(items: &[T]) -> Box + '_> { + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. From 731ea85f215f03fc33a92147d6cc51a01dee589f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 26 May 2020 17:20:08 -0700 Subject: [PATCH 05/10] review comment: tweak wording and account for span overlap --- .../infer/error_reporting/mod.rs | 3 +-- .../nice_region_error/static_impl_trait.rs | 19 +++++++++++++++++-- .../ui/async-await/issues/issue-62097.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 6 +++--- .../static-return-lifetime-infered.stderr | 4 ++-- src/test/ui/issues/issue-16922.stderr | 2 +- ...ect-lifetime-default-from-box-error.stderr | 5 +---- .../region-object-lifetime-in-coercion.stderr | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 2 +- .../missing-lifetimes-in-signature.stderr | 6 +++--- .../dyn-trait-underscore.stderr | 10 ++++++---- 12 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index a7b40d39215..d00c90d06e4 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1806,8 +1806,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { |err: &mut DiagnosticBuilder<'tcx>, type_param_span: Option<(Span, bool, bool)>, bound_kind: GenericKind<'tcx>| { - let msg = "consider introducing an explicit lifetime bound to unify the type \ - parameter and the output"; + let msg = "consider introducing an explicit lifetime bound"; if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span { let suggestion = if is_impl_trait { (sp.shrink_to_hi(), format!(" + {}", new_lt)) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 1a8b7fda179..5c5c86a4fb1 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -27,8 +27,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let return_sp = sub_origin.span(); let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - err.span_label(return_sp, "this evaluates to the `'static` lifetime..."); - err.span_label(sup_origin.span(), "...but this borrow..."); + if sp == sup_origin.span() && return_sp == sp { + // Example: `ui/object-lifetime/object-lifetime-default-from-box-error.rs` + err.span_label( + sup_origin.span(), + "this needs to be `'static` but the borrow...", + ); + } else { + err.span_label(return_sp, "this is `'static`..."); + // We try to make the output have fewer overlapping spans if possible. + if sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()) { + // When `sp == sup_origin` we already have overlapping spans in the + // main diagnostic output, so we don't split this into its own note. + err.span_label(sup_origin.span(), "...but this borrow..."); + } else { + err.span_note(sup_origin.span(), "...but this borrow..."); + } + } let (lifetime, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r); if let Some(lifetime_sp) = lt_sp_opt { diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index cd141b82e41..161b2565c3d 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | pub async fn run_dummy_fn(&self) { | ^^^^^ ...but this borrow... LL | foo(|| self.bar()).await; - | --- this evaluates to the `'static` lifetime... + | --- this is `'static`... | note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31 --> $DIR/issue-62097.rs:12:31 diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 42667d6ca1a..9d068d70bd4 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | fn elided(x: &i32) -> impl Copy { x } | --------- ^ ...but this borrow... | | - | this evaluates to the `'static` lifetime... + | this is `'static`... | note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 --> $DIR/must_outlive_least_region_or_bound.rs:3:1 @@ -22,7 +22,7 @@ error: cannot infer an appropriate lifetime LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | --------- ^ ...but this borrow... | | - | this evaluates to the `'static` lifetime... + | this is `'static`... | note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13 --> $DIR/must_outlive_least_region_or_bound.rs:6:13 @@ -40,7 +40,7 @@ error: cannot infer an appropriate lifetime LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -------------------------------- ^ ...but this borrow... | | - | this evaluates to the `'static` lifetime... + | this is `'static`... | note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15 --> $DIR/must_outlive_least_region_or_bound.rs:12:15 diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 963de2d448d..645c7e1e195 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----------------------- this evaluates to the `'static` lifetime... + | ----------------------- this is `'static`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | @@ -24,7 +24,7 @@ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | ----------------------- this evaluates to the `'static` lifetime... + | ----------------------- this is `'static`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 8bcfe979ce1..20a6b287429 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -5,7 +5,7 @@ LL | Box::new(value) as Box | ---------^^^^^- | | | | | ...but this borrow... - | this evaluates to the `'static` lifetime... + | this is `'static`... | note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 --> $DIR/issue-16922.rs:3:1 diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 7981d082c80..465409c6398 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -2,10 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | ss.r - | ^^^^ - | | - | this evaluates to the `'static` lifetime... - | ...but this borrow... + | ^^^^ this needs to be `'static` but the borrow... | note: ...can't outlive the anonymous lifetime #2 defined on the function body at 14:1 --> $DIR/object-lifetime-default-from-box-error.rs:14:1 diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 8048b79b015..5a414c477a6 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -21,7 +21,7 @@ LL | Box::new(v) | ---------^- | | | | | ...but this borrow... - | this evaluates to the `'static` lifetime... + | this is `'static`... | note: ...can't outlive the anonymous lifetime #1 defined on the function body at 17:1 --> $DIR/region-object-lifetime-in-coercion.rs:17:1 diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index fcde3bb5ca6..21775539cea 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- this evaluates to the `'static` lifetime... + | ^^^^ ---------- this is `'static`... | | | ...but this borrow... | diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index c89ee27aa8c..e931cec8a2a 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ^^^^ ...but this borrow... | | - | this evaluates to the `'static` lifetime... + | this is `'static`... | note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:5 diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 5a2530bdcbb..d6d2a0c4d2b 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,7 +10,7 @@ error: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------------- this evaluates to the `'static` lifetime... + | ------------- this is `'static`... ... LL | / move || { LL | | *dest = g.get(); @@ -55,7 +55,7 @@ note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: | LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^^^^^^^^^^^^^^^ -help: consider introducing an explicit lifetime bound to unify the type parameter and the output +help: consider introducing an explicit lifetime bound | LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ^^^^^ ^^^^ @@ -82,7 +82,7 @@ note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: | LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^^^^^^^^^^^^^^^ -help: consider introducing an explicit lifetime bound to unify the type parameter and the output +help: consider introducing an explicit lifetime bound | LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b | ^^^ ^^^^^^^ ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 65714d16a81..bcbdec4f306 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -2,11 +2,13 @@ error: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | Box::new(items.iter()) - | ---------------^^^^--- - | | | - | | ...but this borrow... - | this evaluates to the `'static` lifetime... + | ---------------^^^^--- this is `'static`... | +note: ...but this borrow... + --> $DIR/dyn-trait-underscore.rs:8:14 + | +LL | Box::new(items.iter()) + | ^^^^^ note: ...can't outlive the anonymous lifetime #1 defined on the function body at 6:1 --> $DIR/dyn-trait-underscore.rs:6:1 | From 1d9472b4700ed64a42cf8000d182152255bce1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 26 May 2020 17:22:47 -0700 Subject: [PATCH 06/10] Update nll tests --- src/test/ui/issues/issue-16922.nll.stderr | 10 ++++++++++ .../object-lifetime-default-from-box-error.nll.stderr | 6 +++--- .../region-object-lifetime-in-coercion.nll.stderr | 10 +++++----- .../dyn-trait-underscore.nll.stderr | 11 +++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/issues/issue-16922.nll.stderr create mode 100644 src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr diff --git a/src/test/ui/issues/issue-16922.nll.stderr b/src/test/ui/issues/issue-16922.nll.stderr new file mode 100644 index 00000000000..7f4f5b22eb3 --- /dev/null +++ b/src/test/ui/issues/issue-16922.nll.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-16922.rs:4:5 + | +LL | fn foo(value: &T) -> Box { + | - let's call the lifetime of this reference `'1` +LL | Box::new(value) as Box + | ^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr index f6252f4ed79..9563c0dff36 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr @@ -1,11 +1,11 @@ -error[E0621]: explicit lifetime required in the type of `ss` +error: lifetime may not live long enough --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>` + | -- has type `&mut SomeStruct<'1>` ... LL | ss.r - | ^^^^ lifetime `'static` required + | ^^^^ returning this value requires that `'1` must outlive `'static` error[E0507]: cannot move out of `ss.r` which is behind a mutable reference --> $DIR/object-lifetime-default-from-box-error.rs:18:5 diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index 767853d8148..bf02ba8eb91 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -14,17 +14,17 @@ LL | fn b(v: &[u8]) -> Box { LL | Box::new(v) | ^^^^^^^^^^^ lifetime `'static` required -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:21:5 +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:20:5 | LL | fn c(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | - let's call the lifetime of this reference `'1` ... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough - --> $DIR/region-object-lifetime-in-coercion.rs:26:5 + --> $DIR/region-object-lifetime-in-coercion.rs:24:5 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr new file mode 100644 index 00000000000..8ed48bda26e --- /dev/null +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/dyn-trait-underscore.rs:8:5 + | +LL | fn a(items: &[T]) -> Box> { + | - let's call the lifetime of this reference `'1` +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | Box::new(items.iter()) + | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + From 8f7ee34379240e7c29c7dda867905e2d0044bde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 27 May 2020 11:15:58 -0700 Subject: [PATCH 07/10] Tweak type parameter errors to reduce verbosity --- .../infer/error_reporting/note.rs | 34 ++++++++----- .../builtin-superkinds-self-type.stderr | 8 +--- ...-infer_static_outlives_requirements.stderr | 8 +--- .../impl_bounds.stderr | 6 +-- .../must_outlive_least_region_or_bound.stderr | 8 +--- .../type_parameters_captured.stderr | 8 +--- .../lifetime-doesnt-live-long-enough.stderr | 46 +++--------------- ...ection-where-clause-env-wrong-bound.stderr | 6 +-- ...ion-where-clause-env-wrong-lifetime.stderr | 6 +-- ...s-close-associated-type-into-object.stderr | 24 ++-------- .../regions-close-object-into-object-5.stderr | 48 +++---------------- ...regions-close-over-type-parameter-1.stderr | 16 +------ .../regions-close-param-into-object.stderr | 32 ++----------- .../ui/regions/regions-enum-not-wf.stderr | 35 ++------------ ...ons-implied-bounds-projection-gap-1.stderr | 8 +--- ...regions-infer-bound-from-trait-self.stderr | 6 +-- .../regions-infer-bound-from-trait.stderr | 16 +------ .../dont-infer-static.stderr | 8 +--- .../regions-enum-not-wf.stderr | 35 ++------------ .../regions-struct-not-wf.stderr | 16 +------ .../missing-lifetimes-in-signature.stderr | 8 +--- .../suggest-impl-trait-lifetime.stderr | 8 +--- ...eric_type_does_not_live_long_enough.stderr | 8 +--- .../wf/wf-impl-associated-type-region.stderr | 8 +--- src/test/ui/wf/wf-in-fn-type-static.stderr | 16 +------ src/test/ui/wf/wf-in-obj-type-static.stderr | 8 +--- .../wf/wf-outlives-ty-in-fn-or-trait.stderr | 16 +------ .../wf/wf-trait-associated-type-region.stderr | 6 +-- 28 files changed, 78 insertions(+), 374 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs index 968c488bc00..9ac27030ade 100644 --- a/src/librustc_infer/infer/error_reporting/note.rs +++ b/src/librustc_infer/infer/error_reporting/note.rs @@ -10,10 +10,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, origin: &SubregionOrigin<'tcx>, ) { + let mut label_or_note = |span, msg| { + let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); + let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); + let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span); + if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { + err.span_label(span, msg); + } else if span_is_primary && expanded_sub_count == 0 { + err.note(msg); + } else { + err.span_note(span, msg); + } + }; match *origin { infer::Subtype(ref trace) => { if let Some((expected, found)) = self.values_str(&trace.values) { - err.span_note( + label_or_note( trace.cause.span, &format!("...so that the {}", trace.cause.as_requirement_str()), ); @@ -24,27 +36,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // handling of region checking when type errors are present is // *terrible*. - err.span_note( + label_or_note( trace.cause.span, &format!("...so that {}", trace.cause.as_requirement_str()), ); } } infer::Reborrow(span) => { - err.span_note(span, "...so that reference does not outlive borrowed content"); + label_or_note(span, "...so that reference does not outlive borrowed content"); } infer::ReborrowUpvar(span, ref upvar_id) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - err.span_note(span, &format!("...so that closure can access `{}`", var_name)); + label_or_note(span, &format!("...so that closure can access `{}`", var_name)); } infer::RelateObjectBound(span) => { - err.span_note(span, "...so that it can be closed over into an object"); + label_or_note(span, "...so that it can be closed over into an object"); } infer::CallReturn(span) => { - err.span_note(span, "...so that return value is valid for the call"); + label_or_note(span, "...so that return value is valid for the call"); } infer::DataBorrowed(ty, span) => { - err.span_note( + label_or_note( span, &format!( "...so that the type `{}` is not borrowed for too long", @@ -53,7 +65,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } infer::ReferenceOutlivesReferent(ty, span) => { - err.span_note( + label_or_note( span, &format!( "...so that the reference type `{}` does not outlive the data it points at", @@ -62,7 +74,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } infer::RelateParamBound(span, t) => { - err.span_note( + label_or_note( span, &format!( "...so that the type `{}` will meet its required lifetime bounds", @@ -71,13 +83,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } infer::RelateRegionParamBound(span) => { - err.span_note( + label_or_note( span, "...so that the declared lifetime parameter bounds are satisfied", ); } infer::CompareImplMethodObligation { span, .. } => { - err.span_note( + label_or_note( span, "...so that the definition in impl matches the definition from the trait", ); diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index 999a5839ba6..2dac4a22ae7 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -2,15 +2,9 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/builtin-superkinds-self-type.rs:10:16 | LL | impl Foo for T { } - | -- ^^^ + | -- ^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/builtin-superkinds-self-type.rs:10:16 - | -LL | impl Foo for T { } - | ^^^ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr index fbc4e8abc42..2beeba8184a 100644 --- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr +++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `U` may not live long enough LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `U: 'static` LL | bar: Bar - | ^^^^^^^^^^^ - | -note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5 - | -LL | bar: Bar - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index d5560c81337..e06977ebbe3 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -5,11 +5,7 @@ LL | type A<'a> where Self: 'static = (&'a ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -note: ...so that the type `Fooy` will meet its required lifetime bounds - --> $DIR/impl_bounds.rs:15:5 - | -LL | type A<'a> where Self: 'static = (&'a ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the type `Fooy` will meet its required lifetime bounds error[E0478]: lifetime bound not satisfied --> $DIR/impl_bounds.rs:17:5 diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 9d068d70bd4..0079fabb58d 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -65,15 +65,9 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:22:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | -- ^^^^^^^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/must_outlive_least_region_or_bound.rs:22:51 - | -LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr index 34f0f7f1d73..40e50b9922f 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.stderr @@ -2,15 +2,9 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/type_parameters_captured.rs:7:20 | LL | fn foo(x: T) -> impl Any + 'static { - | - ^^^^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/type_parameters_captured.rs:7:20 - | -LL | fn foo(x: T) -> impl Any + 'static { - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index e60c461743c..d682478db0e 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `T` may not live long enough LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | foo: &'static T - | ^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5 - | -LL | foo: &'static T - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `K` may not live long enough LL | trait X: Sized { | - help: consider adding an explicit lifetime bound...: `K: 'a` LL | fn foo<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 - | -LL | fn foo<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at error[E0309]: the parameter type `Self` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19 @@ -33,25 +21,15 @@ LL | fn bar<'a, L: X<&'a Nested>>(); | ^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `Self: 'a`... -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19 - | -LL | fn bar<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^^^^ + = note: ...so that the reference type `&'a Nested` does not outlive the data it points at error[E0309]: the parameter type `L` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 | LL | fn baz<'a, L, M: X<&'a Nested>>() { - | - ^^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at | | | help: consider adding an explicit lifetime bound...: `L: 'a` - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 - | -LL | fn baz<'a, L, M: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 @@ -59,25 +37,15 @@ error[E0309]: the parameter type `K` may not live long enough LL | impl Nested { | - help: consider adding an explicit lifetime bound...: `K: 'a` LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 - | -LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at error[E0309]: the parameter type `M` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 | LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { | ^^^^^^^^^^^^^^^^ -- help: consider adding an explicit lifetime bound...: `M: 'a +` - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 - | -LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { - | ^^^^^^^^^^^^^^^^ + | | + | ...so that the reference type `&'a Nested` does not outlive the data it points at error: aborting due to 6 previous errors diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr index 1a5a3719fd8..eba00c5a945 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -5,11 +5,7 @@ LL | bar::() | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Output: 'a`... -note: ...so that the type `>::Output` will meet its required lifetime bounds - --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5 - | -LL | bar::() - | ^^^^^^^^^^^^^^^^ + = note: ...so that the type `>::Output` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr index d6ade2a603e..34b83859a6b 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr @@ -5,11 +5,7 @@ LL | bar::<>::Output>() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Output: 'a`... -note: ...so that the type `>::Output` will meet its required lifetime bounds - --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5 - | -LL | bar::<>::Output>() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the type `>::Output` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.stderr b/src/test/ui/regions/regions-close-associated-type-into-object.stderr index 2401f549a56..9303e0f8e66 100644 --- a/src/test/ui/regions/regions-close-associated-type-into-object.stderr +++ b/src/test/ui/regions/regions-close-associated-type-into-object.stderr @@ -5,11 +5,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'static`... -note: ...so that the type `::Item` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:15:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0310]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:22:5 @@ -18,11 +14,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'static`... -note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:22:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds error[E0309]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:28:5 @@ -31,11 +23,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'a`... -note: ...so that the type `::Item` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:28:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0309]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:35:5 @@ -44,11 +32,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'a`... -note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:35:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr index 2bcdcd1864e..e5a80cbd547 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr @@ -5,13 +5,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^^^^^^^^ - | -note: ...so that the type `B<'_, T>` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:5 - | -LL | box B(&*v) as Box - | ^^^^^^^^^^ + | ^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:9 @@ -20,13 +14,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:9 - | -LL | box B(&*v) as Box - | ^ + | ^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:9 @@ -35,13 +23,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:9 - | -LL | box B(&*v) as Box - | ^^^^^^ + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 @@ -50,13 +32,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^ - | -note: ...so that the reference type `&dyn A` does not outlive the data it points at - --> $DIR/regions-close-object-into-object-5.rs:17:11 - | -LL | box B(&*v) as Box - | ^^^ + | ^^^ ...so that the reference type `&dyn A` does not outlive the data it points at error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 @@ -65,13 +41,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^ - | -note: ...so that the type `(dyn A + 'static)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-5.rs:17:11 - | -LL | box B(&*v) as Box - | ^^^ + | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 @@ -80,13 +50,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^ - | -note: ...so that the type `(dyn A + 'static)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-5.rs:17:11 - | -LL | box B(&*v) as Box - | ^^^ + | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long error: aborting due to 6 previous errors diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr index a7509cb608c..50274b066df 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `A` may not live long enough LL | fn make_object1(v: A) -> Box { | -- help: consider adding an explicit lifetime bound...: `A: 'static +` LL | box v as Box - | ^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-close-over-type-parameter-1.rs:12:5 - | -LL | box v as Box - | ^^^^^ + | ^^^^^ ...so that the type `A` will meet its required lifetime bounds error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:21:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `A` may not live long enough LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box { | -- help: consider adding an explicit lifetime bound...: `A: 'b +` LL | box v as Box - | ^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-close-over-type-parameter-1.rs:21:5 - | -LL | box v as Box - | ^^^^^ + | ^^^^^ ...so that the type `A` will meet its required lifetime bounds error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr index 3b1a89d9ced..705d21078ec 100644 --- a/src/test/ui/regions/regions-close-param-into-object.stderr +++ b/src/test/ui/regions/regions-close-param-into-object.stderr @@ -5,13 +5,7 @@ LL | fn p1(v: T) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'static` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:6:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:12:5 @@ -20,13 +14,7 @@ LL | fn p2(v: Box) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'static` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `std::boxed::Box` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:12:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `std::boxed::Box` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:18:5 @@ -35,13 +23,7 @@ LL | fn p3<'a,T>(v: T) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:18:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:24:5 @@ -50,13 +32,7 @@ LL | fn p4<'a,T>(v: Box) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `std::boxed::Box` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:24:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `std::boxed::Box` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr index 297fcb088d2..e32a36f72cd 100644 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ b/src/test/ui/regions/regions-enum-not-wf.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:18:18 - | -LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:23:25 @@ -19,13 +13,7 @@ LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:23:25 - | -LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:1 @@ -37,16 +25,7 @@ LL | enum RefDouble<'a, 'b, T> { LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) LL | | LL | | } - | |_^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | / enum RefDouble<'a, 'b, T> { -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ + | |_^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:36:23 @@ -54,13 +33,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:36:23 - | -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr index 2f1a4cea8e9..ea59ea11a14 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr @@ -5,13 +5,7 @@ LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) | -- help: consider adding an explicit lifetime bound...: `T: 'x +` LL | { LL | wf::<&'x T>(); - | ^^^^^ - | -note: ...so that the reference type `&'x T` does not outlive the data it points at - --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10 - | -LL | wf::<&'x T>(); - | ^^^^^ + | ^^^^^ ...so that the reference type `&'x T` does not outlive the data it points at error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr index bcdadd7a73d..4ca5ac291d5 100644 --- a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr +++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr @@ -5,11 +5,7 @@ LL | check_bound(x, self) | ^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `Self: 'a`... -note: ...so that the type `Self` will meet its required lifetime bounds - --> $DIR/regions-infer-bound-from-trait-self.rs:46:9 - | -LL | check_bound(x, self) - | ^^^^^^^^^^^ + = note: ...so that the type `Self` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr index a5a0ff52fac..196ee8ca7c0 100644 --- a/src/test/ui/regions/regions-infer-bound-from-trait.stderr +++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `A` may not live long enough LL | fn bar1<'a,A>(x: Inv<'a>, a: A) { | - help: consider adding an explicit lifetime bound...: `A: 'a` LL | check_bound(x, a) - | ^^^^^^^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-infer-bound-from-trait.rs:33:5 - | -LL | check_bound(x, a) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-infer-bound-from-trait.rs:37:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `A` may not live long enough LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) { | -- help: consider adding an explicit lifetime bound...: `A: 'a +` LL | check_bound(x, a) - | ^^^^^^^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-infer-bound-from-trait.rs:37:5 - | -LL | check_bound(x, a) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr index c3cfc5a4d97..2bb51731583 100644 --- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `U` may not live long enough LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `U: 'static` LL | bar: Bar - | ^^^^^^^^^^^ - | -note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/dont-infer-static.rs:8:5 - | -LL | bar: Bar - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index 297fcb088d2..e32a36f72cd 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:18:18 - | -LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:23:25 @@ -19,13 +13,7 @@ LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:23:25 - | -LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:1 @@ -37,16 +25,7 @@ LL | enum RefDouble<'a, 'b, T> { LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) LL | | LL | | } - | |_^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | / enum RefDouble<'a, 'b, T> { -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ + | |_^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:36:23 @@ -54,13 +33,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:36:23 - | -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr index f6658891fa6..44812a51778 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for usize { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a T; - | ^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a T` does not outlive the data it points at - --> $DIR/regions-struct-not-wf.rs:13:5 - | -LL | type Out = &'a T; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-struct-not-wf.rs:21:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for u32 { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = RefOk<'a, T>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-struct-not-wf.rs:21:5 - | -LL | type Out = RefOk<'a, T>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references --> $DIR/regions-struct-not-wf.rs:25:5 diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index d6d2a0c4d2b..0bd335e58e5 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -99,15 +99,9 @@ error[E0309]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:69:44 | LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a - | - ^^^^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:74:5: 76:6 g:G, dest:&mut T]` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `G: 'a` - | -note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:74:5: 76:6 g:G, dest:&mut T]` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:69:44 - | -LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a - | ^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr index b6e6c0bbf32..643dac25724 100644 --- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -5,13 +5,7 @@ LL | fn foo(d: impl Debug) { | ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static` LL | LL | bar(d); - | ^^^ - | -note: ...so that the type `impl Debug` will meet its required lifetime bounds - --> $DIR/suggest-impl-trait-lifetime.rs:7:5 - | -LL | bar(d); - | ^^^ + | ^^^ ...so that the type `impl Debug` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 22e2391f838..e2540e424cb 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -22,16 +22,10 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/generic_type_does_not_live_long_enough.rs:9:1 | LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds ... LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/generic_type_does_not_live_long_enough.rs:9:1 - | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr index 9942c80effe..f3b32ad3f7e 100644 --- a/src/test/ui/wf/wf-impl-associated-type-region.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Foo<'a> for T { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Bar = &'a T; - | ^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a T` does not outlive the data it points at - --> $DIR/wf-impl-associated-type-region.rs:10:5 - | -LL | type Bar = &'a T; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr index 7dc8f5a9661..a79c4462477 100644 --- a/src/test/ui/wf/wf-in-fn-type-static.stderr +++ b/src/test/ui/wf/wf-in-fn-type-static.stderr @@ -5,13 +5,7 @@ LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: 'static LL | x: fn() -> &'static T - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/wf-in-fn-type-static.rs:13:5 - | -LL | x: fn() -> &'static T - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-fn-type-static.rs:18:5 @@ -20,13 +14,7 @@ LL | struct Bar { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: Copy LL | x: fn(&'static T) - | ^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/wf-in-fn-type-static.rs:18:5 - | -LL | x: fn(&'static T) - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr index 32c3198d55b..c0057f3c829 100644 --- a/src/test/ui/wf/wf-in-obj-type-static.stderr +++ b/src/test/ui/wf/wf-in-obj-type-static.stderr @@ -5,13 +5,7 @@ LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: 'static LL | x: dyn Object<&'static T> - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/wf-in-obj-type-static.rs:14:5 - | -LL | x: dyn Object<&'static T> - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error: aborting due to previous error diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr index 52786fb3bca..4c25ab95939 100644 --- a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr +++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for usize { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a fn(T); - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a fn(T)` does not outlive the data it points at - --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5 - | -LL | type Out = &'a fn(T); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for u32 { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a dyn Baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a (dyn Baz + 'a)` does not outlive the data it points at - --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5 - | -LL | type Out = &'a dyn Baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz + 'a)` does not outlive the data it points at error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-trait-associated-type-region.stderr b/src/test/ui/wf/wf-trait-associated-type-region.stderr index 9bbfad90cdb..ae681ba6c9b 100644 --- a/src/test/ui/wf/wf-trait-associated-type-region.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-region.stderr @@ -5,11 +5,7 @@ LL | type Type2 = &'a Self::Type1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Type1: 'a`... -note: ...so that the reference type `&'a >::Type1` does not outlive the data it points at - --> $DIR/wf-trait-associated-type-region.rs:9:5 - | -LL | type Type2 = &'a Self::Type1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the reference type `&'a >::Type1` does not outlive the data it points at error: aborting due to previous error From 224ad326ea4c9d32309fbd46592661a464360b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 27 May 2020 15:33:23 -0700 Subject: [PATCH 08/10] Account for enclosing item when suggesting new lifetime name --- .../infer/error_reporting/mod.rs | 40 ++++++++++++++----- .../nice_region_error/different_lifetimes.rs | 6 +-- .../missing-lifetimes-in-signature.nll.stderr | 29 +++++++++++--- .../missing-lifetimes-in-signature.rs | 10 +++++ .../missing-lifetimes-in-signature.stderr | 34 ++++++++++++++-- 5 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index d00c90d06e4..c2dd3812fcc 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -60,7 +60,7 @@ use rustc_errors::{pluralize, struct_span_err}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::Node; +use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, @@ -1685,12 +1685,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let hir = &self.tcx.hir(); // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. - let generics = self - .in_progress_tables - .and_then(|table| table.borrow().hir_owner) - .map(|table_owner| self.tcx.generics_of(table_owner.to_def_id())); + let generics = + self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| { + let hir_id = hir.as_local_hir_id(table_owner); + let parent_id = hir.get_parent_item(hir_id); + ( + // Parent item could be a `mod`, so we check the HIR before calling: + if let Some(Node::Item(Item { + kind: ItemKind::Trait(..) | ItemKind::Impl { .. }, + .. + })) = hir.find(parent_id) + { + Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id())) + } else { + None + }, + self.tcx.generics_of(table_owner.to_def_id()), + ) + }); let type_param_span = match (generics, bound_kind) { - (Some(ref generics), GenericKind::Param(ref param)) => { + (Some((_, ref generics)), GenericKind::Param(ref param)) => { // Account for the case where `param` corresponds to `Self`, // which doesn't have the expected type argument. if !(generics.has_self && param.index == 0) { @@ -1727,21 +1741,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let new_lt = generics .as_ref() - .and_then(|g| { + .and_then(|(parent_g, g)| { let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"]; - let lts_names = g + let mut lts_names = g .params .iter() .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) .map(|p| p.name.as_str()) .collect::>(); + if let Some(g) = parent_g { + lts_names.extend( + g.params + .iter() + .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) + .map(|p| p.name.as_str()), + ); + } let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s) }) .unwrap_or("'lt"); let add_lt_sugg = generics .as_ref() - .and_then(|g| g.params.first()) + .and_then(|(_, g)| g.params.first()) .and_then(|param| param.def_id.as_local()) .map(|def_id| { (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt)) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs index d206a30d526..7ab18e54f7e 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -121,16 +121,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { (Some(ret_span), _) => ( ty_sub.span, ret_span, - "this parameter and the return type are declared \ - with different lifetimes..." + "this parameter and the return type are declared with different lifetimes..." .to_owned(), format!("...but data{} is returned here", span_label_var1), ), (_, Some(ret_span)) => ( ty_sup.span, ret_span, - "this parameter and the return type are declared \ - with different lifetimes..." + "this parameter and the return type are declared with different lifetimes..." .to_owned(), format!("...but data{} is returned here", span_label_var1), ), diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr index f11c978aabf..2072b00f7b2 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr @@ -56,13 +56,30 @@ LL | | } | |_^ error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:58:45 + --> $DIR/missing-lifetimes-in-signature.rs:59:58 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5... + --> $DIR/missing-lifetimes-in-signature.rs:59:5 + | +LL | / fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { +LL | | +LL | | move || { +LL | | *dest = g.get(); +LL | | } +LL | | } + | |_____^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:68:45 | LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 58:1... - --> $DIR/missing-lifetimes-in-signature.rs:58:1 +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 68:1... + --> $DIR/missing-lifetimes-in-signature.rs:68:1 | LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a LL | | @@ -74,7 +91,7 @@ LL | | } | |_^ error[E0621]: explicit lifetime required in the type of `dest` - --> $DIR/missing-lifetimes-in-signature.rs:63:5 + --> $DIR/missing-lifetimes-in-signature.rs:73:5 | LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` @@ -85,14 +102,14 @@ LL | | } | |_____^ lifetime `'a` required error[E0309]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:69:44 + --> $DIR/missing-lifetimes-in-signature.rs:79:44 | LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a | ^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `G: 'a`... -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0261, E0309, E0621. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index 589d04c9b19..d3853445dfd 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -54,6 +54,16 @@ where } } +// Same as above, but show that we pay attention to lifetime names from parent item +impl<'a> Foo { + fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + //~^ ERROR the parameter type `G` may not live long enough + move || { + *dest = g.get(); + } + } +} + // After applying suggestion for `qux`: fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a //~^ ERROR explicit lifetime required in the type of `dest` diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 0bd335e58e5..46fd0e1052e 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -87,8 +87,34 @@ help: consider introducing an explicit lifetime bound LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b | ^^^ ^^^^^^^ ^^^^ +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:59:58 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5... + --> $DIR/missing-lifetimes-in-signature.rs:59:5 + | +LL | / fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { +LL | | +LL | | move || { +LL | | *dest = g.get(); +LL | | } +LL | | } + | |_____^ +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:59:58 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime bound + | +LL | fn qux<'c, 'b, G: 'c + Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c { + | ^^^ ^^^^^^^ ^^^^ + error[E0621]: explicit lifetime required in the type of `dest` - --> $DIR/missing-lifetimes-in-signature.rs:58:45 + --> $DIR/missing-lifetimes-in-signature.rs:68:45 | LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required @@ -96,14 +122,14 @@ LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a | help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` error[E0309]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:69:44 + --> $DIR/missing-lifetimes-in-signature.rs:79:44 | LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a - | - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:74:5: 76:6 g:G, dest:&mut T]` will meet its required lifetime bounds + | - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6 g:G, dest:&mut T]` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `G: 'a` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0261, E0309, E0621. For more information about an error, try `rustc --explain E0261`. From 6dcd744df0ed404b58767e17f55e1b4f1351daa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 27 May 2020 15:44:42 -0700 Subject: [PATCH 09/10] Consider all possible one letter lifetimes in suggestion --- src/librustc_infer/infer/error_reporting/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index c2dd3812fcc..a59a91e3005 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1742,7 +1742,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let new_lt = generics .as_ref() .and_then(|(parent_g, g)| { - let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"]; + let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect(); let mut lts_names = g .params .iter() @@ -1758,9 +1758,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); - possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s) + possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str())) }) - .unwrap_or("'lt"); + .unwrap_or("'lt".to_string()); let add_lt_sugg = generics .as_ref() .and_then(|(_, g)| g.params.first()) From 83f6f2235892853c152d08551975525b7ae79914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 28 May 2020 11:54:40 -0700 Subject: [PATCH 10/10] Tweak wording and spans of `'static` `dyn Trait`/`impl Trait` requirements --- .../nice_region_error/static_impl_trait.rs | 47 ++++++++++--------- .../ui/async-await/issues/issue-62097.stderr | 13 ++--- .../must_outlive_least_region_or_bound.stderr | 42 ++++++----------- .../static-return-lifetime-infered.stderr | 28 ++++------- src/test/ui/issues/issue-16922.stderr | 16 ++----- ...ect-lifetime-default-from-box-error.stderr | 17 ++----- .../region-object-lifetime-in-coercion.stderr | 18 +++---- ...types_pin_lifetime_impl_trait-async.stderr | 13 ++--- ..._self_types_pin_lifetime_impl_trait.stderr | 14 ++---- .../missing-lifetimes-in-signature.stderr | 19 ++------ .../dyn-trait-underscore.stderr | 20 ++------ 11 files changed, 91 insertions(+), 156 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 5c5c86a4fb1..f4c86ddae60 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -27,28 +27,32 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let return_sp = sub_origin.span(); let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - if sp == sup_origin.span() && return_sp == sp { - // Example: `ui/object-lifetime/object-lifetime-default-from-box-error.rs` - err.span_label( - sup_origin.span(), - "this needs to be `'static` but the borrow...", - ); - } else { - err.span_label(return_sp, "this is `'static`..."); - // We try to make the output have fewer overlapping spans if possible. - if sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()) { - // When `sp == sup_origin` we already have overlapping spans in the - // main diagnostic output, so we don't split this into its own note. - err.span_label(sup_origin.span(), "...but this borrow..."); + let param_info = self.find_param_with_region(sup_r, sub_r)?; + err.span_label(param_info.param_ty_span, "data with this lifetime..."); + + // We try to make the output have fewer overlapping spans if possible. + if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) + && sup_origin.span() != return_sp + { + // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` + + // Customize the spans and labels depending on their relative order so + // that split sentences flow correctly. + if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() { + err.span_label(sup_origin.span(), "...is captured here..."); + err.span_label(return_sp, "...and required to be `'static` by this"); } else { - err.span_note(sup_origin.span(), "...but this borrow..."); + err.span_label(return_sp, "...is required to be `'static` by this..."); + err.span_label(sup_origin.span(), "...and is captured here"); } + } else { + err.span_label( + return_sp, + "...is captured and required to be `'static` here", + ); } - let (lifetime, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r); - if let Some(lifetime_sp) = lt_sp_opt { - err.span_note(lifetime_sp, &format!("...can't outlive {}", lifetime)); - } + let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r); let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; @@ -56,10 +60,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // explicit non-desugar'able return. if fn_return_span.desugaring_kind().is_none() { let msg = format!( - "you can add a bound to the returned `{} Trait` to make it last less \ - than `'static` and match {}", + "to permit non-static references in {} `{} Trait` value, you can add \ + an explicit bound for {}", + if is_dyn { "a" } else { "an" }, if is_dyn { "dyn" } else { "impl" }, - lifetime + lifetime, ); // FIXME: account for the need of parens in `&(dyn Trait + '_)` err.span_suggestion_verbose( diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 161b2565c3d..af8fc2cd2ab 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -2,15 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { - | ^^^^^ ...but this borrow... + | ^^^^^ + | | + | data with this lifetime... + | ...is captured here... LL | foo(|| self.bar()).await; - | --- this is `'static`... - | -note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31 - --> $DIR/issue-62097.rs:12:31 - | -LL | pub async fn run_dummy_fn(&self) { - | ^ + | --- ...and required to be `'static` by this error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 0079fabb58d..d7dae6a08a7 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -2,16 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | --------- ^ ...but this borrow... - | | - | this is `'static`... + | ---- --------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 - --> $DIR/must_outlive_least_region_or_bound.rs:3:1 - | -LL | fn elided(x: &i32) -> impl Copy { x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ @@ -20,16 +16,12 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | --------- ^ ...but this borrow... - | | - | this is `'static`... + | ------- --------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13 - --> $DIR/must_outlive_least_region_or_bound.rs:6:13 - | -LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | ^^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ @@ -38,16 +30,12 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | -------------------------------- ^ ...but this borrow... - | | - | this is `'static`... + | ------- -------------------------------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15 - --> $DIR/must_outlive_least_region_or_bound.rs:12:15 - | -LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | ^^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } | ^^^^ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 645c7e1e195..1c3a5979ee5 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,20 +2,15 @@ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----------------------- this is `'static`... + | ----- ----------------------- ...is required to be `'static` by this... + | | + | data with this lifetime... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...but this borrow... + | ...and is captured here | -note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5 - --> $DIR/static-return-lifetime-infered.rs:6:5 - | -LL | / fn iter_values_anon(&self) -> impl Iterator { -LL | | self.x.iter().map(|a| a.0) -LL | | } - | |_____^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ @@ -24,18 +19,15 @@ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | ----------------------- this is `'static`... + | -------- ----------------------- ...is required to be `'static` by this... + | | + | data with this lifetime... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...but this borrow... + | ...and is captured here | -note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20 - --> $DIR/static-return-lifetime-infered.rs:10:20 - | -LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | ^^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^ diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 20a6b287429..02d33aae023 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,21 +1,15 @@ error: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | +LL | fn foo(value: &T) -> Box { + | -- data with this lifetime... LL | Box::new(value) as Box | ---------^^^^^- | | | - | | ...but this borrow... - | this is `'static`... + | | ...and is captured here + | ...is required to be `'static` by this... | -note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 - --> $DIR/issue-16922.rs:3:1 - | -LL | / fn foo(value: &T) -> Box { -LL | | Box::new(value) as Box -LL | | -LL | | } - | |_^ -help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 465409c6398..70a9bf22b8d 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,20 +1,13 @@ error: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | +LL | fn load(ss: &mut SomeStruct) -> Box { + | --------------- data with this lifetime... +... LL | ss.r - | ^^^^ this needs to be `'static` but the borrow... + | ^^^^ ...is captured and required to be `'static` here | -note: ...can't outlive the anonymous lifetime #2 defined on the function body at 14:1 - --> $DIR/object-lifetime-default-from-box-error.rs:14:1 - | -LL | / fn load(ss: &mut SomeStruct) -> Box { -LL | | // `Box` defaults to a `'static` bound, so this return -LL | | // is illegal. -LL | | -LL | | ss.r -LL | | } - | |_^ -help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #2 defined on the function body at 14:1 +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 5a414c477a6..1462af44cb1 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -17,22 +17,16 @@ LL | Box::new(v) error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:20:14 | +LL | fn c(v: &[u8]) -> Box { + | ----- data with this lifetime... +... LL | Box::new(v) | ---------^- | | | - | | ...but this borrow... - | this is `'static`... + | | ...and is captured here + | ...is required to be `'static` by this... | -note: ...can't outlive the anonymous lifetime #1 defined on the function body at 17:1 - --> $DIR/region-object-lifetime-in-coercion.rs:17:1 - | -LL | / fn c(v: &[u8]) -> Box { -LL | | // same as previous case due to RFC 599 -LL | | -LL | | Box::new(v) -LL | | } - | |_^ -help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 17:1 +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1 | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 21775539cea..1aeabce5e8a 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,15 +2,10 @@ error: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- this is `'static`... - | | - | ...but this borrow... - | -note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26 - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:26 - | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^ + | ^^^^ ---------- ---------- ...and required to be `'static` by this + | | | + | | data with this lifetime... + | ...is captured here... error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index e931cec8a2a..04c475be787 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -2,16 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ---------- ^^^^ ...but this borrow... - | | - | this is `'static`... + | ---------- ---------- ^^^^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5 - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:5 - | -LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 46fd0e1052e..5cf170d566c 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,25 +10,16 @@ error: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------------- this is `'static`... + | ------ ------------- ...is required to be `'static` by this... + | | + | data with this lifetime... ... LL | / move || { LL | | *dest = g.get(); LL | | } - | |_____^ ...but this borrow... + | |_____^ ...and is captured here | -note: ...can't outlive the anonymous lifetime #1 defined on the function body at 15:1 - --> $DIR/missing-lifetimes-in-signature.rs:15:1 - | -LL | / fn foo(g: G, dest: &mut T) -> impl FnOnce() -LL | | where -LL | | G: Get -LL | | { -... | -LL | | } -LL | | } - | |_^ -help: you can add a bound to the returned `impl Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 15:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index bcbdec4f306..3577dd59289 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,23 +1,13 @@ error: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | +LL | fn a(items: &[T]) -> Box> { + | ---- data with this lifetime... +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ---------------^^^^--- this is `'static`... + | ---------------^^^^--- ...is captured and required to be `'static` here | -note: ...but this borrow... - --> $DIR/dyn-trait-underscore.rs:8:14 - | -LL | Box::new(items.iter()) - | ^^^^^ -note: ...can't outlive the anonymous lifetime #1 defined on the function body at 6:1 - --> $DIR/dyn-trait-underscore.rs:6:1 - | -LL | / fn a(items: &[T]) -> Box> { -LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` -LL | | Box::new(items.iter()) -LL | | } - | |_^ -help: you can add a bound to the returned `dyn Trait` to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 6:1 +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^