Skip to content

Commit 18bc36b

Browse files
committed
Account for RPITIT in E0310 explicit lifetime constraint suggestion
When given ```rust trait Original { fn f() -> impl Fn(); } trait Erased { fn f(&self) -> Box<dyn Fn()>; } impl<T: Original> Erased for T { fn f(&self) -> Box<dyn Fn()> { Box::new(<T as Original>::f()) } } ``` emit a suggestion to further constrain the RPITIT, instead of what we did previously, suggest restricting the `Trait::{opaque}` type in a `where` clause: ``` error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough --> $DIR/missing-static-bound-from-impl.rs:11:9 | LL | Box::new(<T as Original>::f()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime... | ...so that the type `impl Fn()` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | LL | fn f() -> impl Fn() + 'static; | +++++++++ ``` Fix #119773.
1 parent 2dc0170 commit 18bc36b

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -2433,6 +2433,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
24332433
let suggestion =
24342434
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
24352435
suggs.push((sp, suggestion))
2436+
} else if let GenericKind::Alias(ref p) = bound_kind
2437+
&& let ty::Projection = p.kind(self.tcx)
2438+
&& let DefKind::AssocTy = self.tcx.def_kind(p.def_id)
2439+
&& let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
2440+
self.tcx.opt_rpitit_info(p.def_id)
2441+
{
2442+
// The lifetime found in the `impl` is longer than the one on the RPITIT.
2443+
suggs.push((
2444+
self.tcx.def_span(opaque_def_id).shrink_to_hi(),
2445+
format!(" + {lt_name}"),
2446+
));
24362447
} else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) {
24372448
let pred = format!("{bound_kind}: {lt_name}");
24382449
let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred);

tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ LL | async fn foo() -> &'static impl T;
77
| the associated type `<Self as MyTrait>::{opaque#0}` must be valid for the static lifetime...
88
| ...so that the reference type `&'static impl T` does not outlive the data it points at
99
|
10-
= help: consider adding an explicit lifetime bound `<Self as MyTrait>::{opaque#0}: 'static`...
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | async fn foo() -> &'static impl T + 'static;
13+
| +++++++++
1114

1215
error: aborting due to 1 previous error
1316

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait Original {
2+
fn f() -> impl Fn();
3+
}
4+
5+
trait Erased {
6+
fn f(&self) -> Box<dyn Fn()>;
7+
}
8+
9+
impl<T: Original> Erased for T {
10+
fn f(&self) -> Box<dyn Fn()> {
11+
Box::new(<T as Original>::f())
12+
//~^ ERROR the associated type `<T as Original>::{opaque#0}` may not live long enough
13+
}
14+
}
15+
16+
fn main () {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough
2+
--> $DIR/missing-static-bound-from-impl.rs:11:9
3+
|
4+
LL | Box::new(<T as Original>::f())
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime...
8+
| ...so that the type `impl Fn()` will meet its required lifetime bounds
9+
|
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | fn f() -> impl Fn() + 'static;
13+
| +++++++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0310`.

0 commit comments

Comments
 (0)