From ee0fd105d86f4998a341b9a819735f1087423492 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 12 Oct 2021 09:52:32 +0000 Subject: [PATCH] Point at return type when it introduces `'static` obligation --- .../nice_region_error/static_impl_trait.rs | 20 ++++++++++++ .../project-fn-ret-invariant.transmute.stderr | 9 ++++++ .../must_outlive_least_region_or_bound.stderr | 28 ++++++++++++++++ ...ect-lifetime-default-from-box-error.stderr | 8 +++++ .../region-object-lifetime-in-coercion.stderr | 15 +++++++++ .../regions-close-object-into-object-2.stderr | 7 ++++ .../regions-close-object-into-object-4.stderr | 7 ++++ .../regions/regions-proc-bound-capture.stderr | 8 +++++ .../type-checking-test-4.stderr | 32 +++++++++++++++++++ .../dyn-trait-underscore.stderr | 8 +++++ 10 files changed, 142 insertions(+) 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 daeb406a839..34015b97e3c 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 @@ -181,6 +181,26 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { err.span_note(*bound, "`'static` lifetime requirement introduced by this bound"); } + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin { + if let ObligationCauseCode::BlockTailExpression(hir_id) = &cause.code { + 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(), + ); + span.push_span_label( + cause.span, + "because of this returned expression".to_string(), + ); + err.span_note( + span, + "`'static` lifetime requirement introduced by the return type", + ); + } + } + } let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); 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 eb81da7852d..49264ae2505 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 @@ -6,6 +6,15 @@ LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { ... 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 + | +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { + | ^^^^^^^^^^^^^ requirement introduced by this return type +... +LL | bar(foo, x) + | ----------- because of this returned expression 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 e80372766dc..d0d9ed8923d 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 @@ -140,6 +140,13 @@ LL | fn elided3(x: &i32) -> Box { 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 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^^^ ----------- because of this returned expression + | | + | requirement introduced by this return type 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 { Box::new(x) } @@ -153,6 +160,13 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { 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 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^^^ ----------- because of this returned expression + | | + | requirement introduced by this return type 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 { Box::new(x) } @@ -166,6 +180,13 @@ LL | fn elided4(x: &i32) -> Box { 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 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- because of this returned expression + | | + | requirement introduced by this return type help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -181,6 +202,13 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime LL | fn explicit4<'a>(x: &'a i32) -> Box { 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 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- because of this returned expression + | | + | requirement introduced by this return type help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit4<'a>(x: &'a i32) -> Box { 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 e0a8534cd28..c882e3c9d06 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 @@ -7,6 +7,14 @@ LL | fn load(ss: &mut SomeStruct) -> Box { 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 + | +LL | fn load(ss: &mut SomeStruct) -> Box { + | ^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +... +LL | ss.r + | ---- because of this returned expression help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound | 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 9eb24c1bd37..45a3c801a38 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -23,6 +23,13 @@ LL | fn b(v: &[u8]) -> Box { 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 + | +LL | fn b(v: &[u8]) -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +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` | LL | fn b(v: &[u8]) -> Box { @@ -41,6 +48,14 @@ LL | fn c(v: &[u8]) -> Box { 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 + | +LL | fn c(v: &[u8]) -> Box { + | ^^^^^^^^^^^^ requirement introduced by this return type +... +LL | Box::new(v) + | ----------- because of this returned expression help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound | LL | fn c(v: &[u8]) -> Box { 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 9c803d4e1d4..a924fbc5bf7 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 @@ -6,6 +6,13 @@ LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { LL | Box::new(B(&*v)) as Box | ^^^ ...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 + | +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | Box::new(B(&*v)) as Box + | ------------------------------ because of this returned expression help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { 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 27bb19a89df..969222068ee 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 @@ -6,6 +6,13 @@ LL | fn i<'a, T, U>(v: Box+'a>) -> Box { LL | Box::new(B(&*v)) as Box | ^^^ ...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 + | +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | Box::new(B(&*v)) as Box + | ------------------------------ because of this returned expression help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index a257576e5d1..3bbbf00d5e7 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -7,6 +7,14 @@ LL | // This is illegal, because the region bound on `proc` is 'static. 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 + | +LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | // This is illegal, because the region bound on `proc` is 'static. +LL | Box::new(move || { *x }) + | ------------------------ because of this returned expression help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { 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 3d6308a0825..c06943c0874 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 @@ -46,6 +46,14 @@ 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 + | +LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +... +LL | y.get_b() // ERROR + | --------- because of this returned expression error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/type-checking-test-4.rs:33:5 @@ -54,6 +62,14 @@ LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | ------------ this data with lifetime `'a`... 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 + | +LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | <_ as Bar>::get_b(x) // ERROR + | -------------------- because of this returned expression error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/type-checking-test-4.rs:38:15 @@ -62,6 +78,14 @@ LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | ------------ this data with lifetime `'a`... 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 + | +LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR + | ---------------------------- because of this returned expression error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/type-checking-test-4.rs:43:27 @@ -84,6 +108,14 @@ 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 + | +LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +... +LL | z.get_b() // ERROR + | --------- because of this returned expression error: aborting due to 6 previous errors diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index da0f6d0ecde..3fed7ba6c49 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -9,6 +9,14 @@ 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 + | +LL | fn a(items: &[T]) -> Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | Box::new(items.iter()) + | ---------------------- because of this returned expression help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound | LL | fn a(items: &[T]) -> Box + '_> {