From 5e6da720f621308a0f44e7c6bbd13a9fad68b240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 22 Feb 2024 06:15:55 +0000 Subject: [PATCH] Account for RPITIT in E0310 explicit lifetime constraint suggestion When given ```rust trait Original { fn f() -> impl Fn(); } trait Erased { fn f(&self) -> Box; } impl Erased for T { fn f(&self) -> Box { Box::new(::f()) } } ``` avoid suggestion to restrict the `Trait::{opaque}` type in a `where` clause: ``` error[E0310]: the associated type `::{opaque#0}` may not live long enough --> $DIR/missing-static-bound-from-impl.rs:11:9 | LL | Box::new(::f()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | the associated type `::{opaque#0}` must be valid for the static lifetime... | ...so that the type `impl Fn()` will meet its required lifetime bounds ``` CC #119773. --- .../rustc_infer/src/infer/error_reporting/mod.rs | 8 ++++++++ .../impl-trait/in-trait/async-and-ret-ref.stderr | 2 -- .../in-trait/missing-static-bound-from-impl.rs | 16 ++++++++++++++++ .../missing-static-bound-from-impl.stderr | 12 ++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.rs create mode 100644 tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 505d56cf49179..470b97b777835 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2434,6 +2434,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let suggestion = if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") }; suggs.push((sp, suggestion)) + } else if let GenericKind::Alias(ref p) = bound_kind + && let ty::Projection = p.kind(self.tcx) + && let DefKind::AssocTy = self.tcx.def_kind(p.def_id) + && let Some(ty::ImplTraitInTraitData::Trait { .. }) = + self.tcx.opt_rpitit_info(p.def_id) + { + // The lifetime found in the `impl` is longer than the one on the RPITIT. + // Do not suggest `::{opaque}: 'static`. } else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) { let pred = format!("{bound_kind}: {lt_name}"); let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred); diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr index 79a86b0a3aedf..15aa3cf54bbe5 100644 --- a/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr @@ -6,8 +6,6 @@ LL | async fn foo() -> &'static impl T; | | | the associated type `::{opaque#0}` must be valid for the static lifetime... | ...so that the reference type `&'static impl T` does not outlive the data it points at - | - = help: consider adding an explicit lifetime bound `::{opaque#0}: 'static`... error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.rs b/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.rs new file mode 100644 index 0000000000000..a36799c3ebd46 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.rs @@ -0,0 +1,16 @@ +trait Original { + fn f() -> impl Fn(); +} + +trait Erased { + fn f(&self) -> Box; +} + +impl Erased for T { + fn f(&self) -> Box { + Box::new(::f()) + //~^ ERROR the associated type `::{opaque#0}` may not live long enough + } +} + +fn main () {} diff --git a/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr b/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr new file mode 100644 index 0000000000000..5ec0ee38347aa --- /dev/null +++ b/tests/ui/impl-trait/in-trait/missing-static-bound-from-impl.stderr @@ -0,0 +1,12 @@ +error[E0310]: the associated type `::{opaque#0}` may not live long enough + --> $DIR/missing-static-bound-from-impl.rs:11:9 + | +LL | Box::new(::f()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::{opaque#0}` must be valid for the static lifetime... + | ...so that the type `impl Fn()` will meet its required lifetime bounds + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`.