diff options
12 files changed, 85 insertions, 79 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 34015b97e3c..80bdccd4f2c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_middle::ty::{ - self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor, + self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable, + TypeVisitor, }; use rustc_span::symbol::Ident; use rustc_span::{MultiSpan, Span}; @@ -186,10 +187,27 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let parent_id = tcx.hir().get_parent_item(*hir_id); if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) { let mut span: MultiSpan = fn_decl.output.span().into(); - span.push_span_label( - fn_decl.output.span(), - "requirement introduced by this return type".to_string(), - ); + let mut add_label = true; + if let hir::FnRetTy::Return(ty) = fn_decl.output { + let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); + v.visit_ty(ty); + if !v.0.is_empty() { + span = v.0.clone().into(); + for sp in v.0 { + span.push_span_label( + sp, + "`'static` requirement introduced here".to_string(), + ); + } + add_label = false; + } + } + if add_label { + span.push_span_label( + fn_decl.output.span(), + "requirement introduced by this return type".to_string(), + ); + } span.push_span_label( cause.span, "because of this returned expression".to_string(), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 275a2128c45..0bf457ca8a8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1481,40 +1481,8 @@ impl<'tcx> TyCtxt<'tcx> { scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - 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, + let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) { + Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty, _ => return vec![], }; diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 8803370251b..1acb3ec57de 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -6,6 +6,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; +use rustc_span::Span; impl<'tcx> TyS<'tcx> { /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. @@ -432,3 +433,22 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { hir::intravisit::walk_ty(self, ty); } } + +/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. +pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>); + +impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> { + type Map = rustc_hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) { + if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = + lt.name + { + self.0.push(lt.span); + } + } +} diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 49264ae2505..628023ad471 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -8,10 +8,10 @@ LL | bar(foo, x) | ^^^ - ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/project-fn-ret-invariant.rs:45:32 + --> $DIR/project-fn-ret-invariant.rs:45:37 | LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { - | ^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here ... LL | bar(foo, x) | ----------- because of this returned expression 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 d0d9ed8923d..bf1f93aebd5 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 @@ -141,12 +141,12 @@ LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } | this data with an anonymous lifetime `'_`... | note: `'static` lifetime requirement introduced by the return type - --> $DIR/must_outlive_least_region_or_bound.rs:14:24 + --> $DIR/must_outlive_least_region_or_bound.rs:14:28 | LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } - | ^^^^^^^^^^^^^^ ----------- because of this returned expression - | | - | requirement introduced by this return type + | ^^^^^^^^^ ----------- because of this returned expression + | | + | `'static` requirement introduced here help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) } @@ -161,12 +161,12 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } | this data with lifetime `'a`... | note: `'static` lifetime requirement introduced by the return type - --> $DIR/must_outlive_least_region_or_bound.rs:16:33 + --> $DIR/must_outlive_least_region_or_bound.rs:16:37 | LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } - | ^^^^^^^^^^^^^^ ----------- because of this returned expression - | | - | requirement introduced by this return type + | ^^^^^^^^^ ----------- because of this returned expression + | | + | `'static` requirement introduced here help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) } @@ -181,12 +181,12 @@ LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } | this data with an anonymous lifetime `'_`... | note: `'static` lifetime requirement introduced by the return type - --> $DIR/must_outlive_least_region_or_bound.rs:18:24 + --> $DIR/must_outlive_least_region_or_bound.rs:18:40 | LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- because of this returned expression - | | - | requirement introduced by this return type + | ^^^^^^^ ----------- because of this returned expression + | | + | `'static` requirement introduced here help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) } @@ -203,12 +203,12 @@ LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } | ------- this data with lifetime `'a`... ^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/must_outlive_least_region_or_bound.rs:20:33 + --> $DIR/must_outlive_least_region_or_bound.rs:20:49 | LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } - | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- because of this returned expression - | | - | requirement introduced by this return type + | ^^^^^^^ ----------- because of this returned expression + | | + | `'static` requirement introduced here help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) } 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 c882e3c9d06..0308ecf8f64 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 @@ -8,10 +8,10 @@ LL | ss.r | ^^^^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/object-lifetime-default-from-box-error.rs:14:33 + --> $DIR/object-lifetime-default-from-box-error.rs:14:37 | LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> { - | ^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^^^^^^^ `'static` requirement introduced here ... LL | ss.r | ---- because of this returned expression 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 45a3c801a38..74683f1439a 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -24,10 +24,10 @@ LL | Box::new(v) | ^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/region-object-lifetime-in-coercion.rs:12:19 + --> $DIR/region-object-lifetime-in-coercion.rs:12:33 | LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> { - | ^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here LL | Box::new(v) | ----------- because of this returned expression help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` @@ -49,10 +49,10 @@ LL | Box::new(v) | ^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/region-object-lifetime-in-coercion.rs:16:19 + --> $DIR/region-object-lifetime-in-coercion.rs:16:23 | LL | fn c(v: &[u8]) -> Box<dyn Foo> { - | ^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here ... LL | Box::new(v) | ----------- because of this returned expression diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index a924fbc5bf7..c914d91306c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -7,10 +7,10 @@ LL | Box::new(B(&*v)) as Box<dyn X> | ^^^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/regions-close-object-into-object-2.rs:8:48 + --> $DIR/regions-close-object-into-object-2.rs:8:60 | LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> { - | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here LL | Box::new(B(&*v)) as Box<dyn X> | ------------------------------ because of this returned expression help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 969222068ee..1f68db023a9 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -7,10 +7,10 @@ LL | Box::new(B(&*v)) as Box<dyn X> | ^^^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/regions-close-object-into-object-4.rs:8:40 + --> $DIR/regions-close-object-into-object-4.rs:8:52 | LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { - | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here LL | Box::new(B(&*v)) as Box<dyn X> | ------------------------------ because of this returned expression help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 3bbbf00d5e7..99657632035 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -8,10 +8,10 @@ LL | Box::new(move || { *x }) | ^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/regions-proc-bound-capture.rs:7:30 + --> $DIR/regions-proc-bound-capture.rs:7:59 | LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) | ------------------------ because of this returned expression diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr index c06943c0874..42230ddd695 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -47,10 +47,10 @@ note: ...and is required to live as long as `'static` here LL | y.get_b() // ERROR | ^^^^^^^^^ note: `'static` lifetime requirement introduced by the return type - --> $DIR/type-checking-test-4.rs:26:40 + --> $DIR/type-checking-test-4.rs:26:48 | LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here ... LL | y.get_b() // ERROR | --------- because of this returned expression @@ -64,10 +64,10 @@ LL | <_ as Bar>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/type-checking-test-4.rs:32:40 + --> $DIR/type-checking-test-4.rs:32:48 | LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here LL | <_ as Bar>::get_b(x) // ERROR | -------------------- because of this returned expression @@ -80,10 +80,10 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR | ----------^^------------- ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/type-checking-test-4.rs:37:40 + --> $DIR/type-checking-test-4.rs:37:48 | LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR | ---------------------------- because of this returned expression @@ -109,10 +109,10 @@ note: ...and is required to live as long as `'static` here LL | z.get_b() // ERROR | ^^^^^^^^^ note: `'static` lifetime requirement introduced by the return type - --> $DIR/type-checking-test-4.rs:42:40 + --> $DIR/type-checking-test-4.rs:42:48 | LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^ `'static` requirement introduced here ... LL | z.get_b() // ERROR | --------- because of this returned expression diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 3fed7ba6c49..b8552c872c1 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -10,10 +10,10 @@ LL | Box::new(items.iter()) | ...is captured and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/dyn-trait-underscore.rs:6:25 + --> $DIR/dyn-trait-underscore.rs:6:29 | LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type + | ^^^^^^^^^^^^^^^^^^^^^ `'static` requirement introduced here LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) | ---------------------- because of this returned expression |
