Special case detecting 'static lifetime requirement coming from -> Box<dyn Trait>

```
error[E0310]: the parameter type `R` may not live long enough
  --> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:10:5
   |
LL | fn bb<R>(r: R) -> Box<dyn Foo> {
   |                       ------- this `dyn Trait` has an implicit `'static` lifetime bound
LL |     Box::new(Bar(r))
   |     ^^^^^^^^^^^^^^^^
   |     |
   |     the parameter type `R` must be valid for the static lifetime...
   |     ...so that the type `R` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
LL | fn bb<R: 'static>(r: R) -> Box<dyn Foo> {
   |        +++++++++
```
This commit is contained in:
Esteban Küber
2025-11-04 22:33:05 +00:00
parent e5efc33672
commit a49d4d7713
6 changed files with 132 additions and 3 deletions
@@ -3568,8 +3568,7 @@ fn add_missing_lifetime_specifiers_label(
&& (lt.kind == MissingLifetimeKind::Ampersand
|| lt.kind == MissingLifetimeKind::Underscore)
{
let pre = if lt.kind == MissingLifetimeKind::Ampersand
&& let Some((kind, _span)) = self.diag_metadata.current_function
let pre = if let Some((kind, _span)) = self.diag_metadata.current_function
&& let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
&& !sig.decl.inputs.is_empty()
&& let sugg = sig
@@ -3599,10 +3598,12 @@ fn add_missing_lifetime_specifiers_label(
} else {
("one of the", "s")
};
let dotdotdot =
if lt.kind == MissingLifetimeKind::Ampersand { "..." } else { "" };
err.multipart_suggestion_verbose(
format!(
"instead, you are more likely to want to change {the} \
argument{s} to be borrowed...",
argument{s} to be borrowed{dotdotdot}",
),
sugg,
Applicability::MaybeIncorrect,
@@ -864,6 +864,42 @@ pub fn construct_generic_bound_failure(
}
}
if sub.kind() == ty::ReStatic
&& let Some(node) = self.tcx.hir_get_if_local(generic_param_scope.into())
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { sig, body, has_body: true, .. },
..
})
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)),
..
})
| hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(sig, body), ..
}) = node
&& let hir::Node::Expr(expr) = self.tcx.hir_node(body.hir_id)
&& let hir::ExprKind::Block(block, _) = expr.kind
&& let Some(tail) = block.expr
&& tail.span == span
&& let hir::FnRetTy::Return(ty) = sig.decl.output
&& let hir::TyKind::Path(path) = ty.kind
&& let hir::QPath::Resolved(None, path) = path
&& let hir::def::Res::Def(_, def_id) = path.res
&& Some(def_id) == self.tcx.lang_items().owned_box()
&& let [segment] = path.segments
&& let Some(args) = segment.args
&& let [hir::GenericArg::Type(ty)] = args.args
&& let hir::TyKind::TraitObject(_, tagged_ref) = ty.kind
&& let hir::LifetimeKind::ImplicitObjectLifetimeDefault = tagged_ref.pointer().kind
{
// Explicitly look for `-> Box<dyn Trait>` to point at it as the *likely* source of
// the `'static` lifetime requirement.
err.span_label(
ty.span,
format!("this `dyn Trait` has an implicit `'static` lifetime bound"),
);
}
err
}
@@ -1,6 +1,8 @@
error[E0310]: the associated type `impl Fn()` may not live long enough
--> $DIR/missing-static-bound-from-impl.rs:11:9
|
LL | fn f(&self) -> Box<dyn Fn()> {
| -------- this `dyn Trait` has an implicit `'static` lifetime bound
LL | Box::new(<T as Original>::f())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
@@ -0,0 +1,35 @@
// #41966
trait Foo {}
struct Bar<R>(R);
impl<R> Foo for Bar<R> {
}
fn bb<R>(r: R) -> Box<dyn Foo> {
Box::new(Bar(r)) //~ ERROR the parameter type `R` may not live long enough
}
fn cc<R>(r: R) -> Box<dyn Foo + '_> { //~ ERROR missing lifetime specifier
Box::new(Bar(r))
}
// #54753
pub struct Qux<T>(T);
pub struct Bazzzz<T>(T);
pub trait Baz {}
impl<T> Baz for Bazzzz<T> {}
impl<T> Qux<T> {
fn baz(self) -> Box<dyn Baz> {
Box::new(Bazzzz(self.0)) //~ ERROR the parameter type `T` may not live long enough
}
}
fn main() {
let a = 10;
let _b = bb(&a);
let _c = cc(&a);
}
@@ -0,0 +1,53 @@
error[E0106]: missing lifetime specifier
--> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:13:33
|
LL | fn cc<R>(r: R) -> Box<dyn Foo + '_> {
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL - fn cc<R>(r: R) -> Box<dyn Foo + '_> {
LL + fn cc<R>(r: R) -> Box<dyn Foo + 'static> {
|
help: instead, you are more likely to want to change the argument to be borrowed
|
LL | fn cc<R>(r: &R) -> Box<dyn Foo + '_> {
| +
error[E0310]: the parameter type `R` may not live long enough
--> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:10:5
|
LL | fn bb<R>(r: R) -> Box<dyn Foo> {
| ------- this `dyn Trait` has an implicit `'static` lifetime bound
LL | Box::new(Bar(r))
| ^^^^^^^^^^^^^^^^
| |
| the parameter type `R` must be valid for the static lifetime...
| ...so that the type `R` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | fn bb<R: 'static>(r: R) -> Box<dyn Foo> {
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:27:9
|
LL | fn baz(self) -> Box<dyn Baz> {
| ------- this `dyn Trait` has an implicit `'static` lifetime bound
LL | Box::new(Bazzzz(self.0))
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | impl<T: 'static> Qux<T> {
| +++++++++
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0106, E0310.
For more information about an error, try `rustc --explain E0106`.
@@ -38,6 +38,8 @@ LL | fn without_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {}
error[E0310]: the parameter type `impl FnOnce(T) -> dyn Future<Output = ()>` may not live long enough
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:6:5
|
LL | ) -> Box<dyn FnOnce(T) -> dyn Future<Output = ()>> {
| ---------------------------------------- this `dyn Trait` has an implicit `'static` lifetime bound
LL | Box::new(executor)
| ^^^^^^^^^^^^^^^^^^
| |