diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 57f81ebf0d81e..6c49a777277f0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3568,8 +3568,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && (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 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } 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, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e225656af852c..da888acc47559 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -864,6 +864,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + 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` 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 } 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 index 1f787c1842cf9..d854a457485dd 100644 --- 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 @@ -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 { + | -------- this `dyn Trait` has an implicit `'static` lifetime bound LL | Box::new(::f()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.rs b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.rs new file mode 100644 index 0000000000000..428033b53065b --- /dev/null +++ b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.rs @@ -0,0 +1,35 @@ +// #41966 +trait Foo {} + +struct Bar(R); + +impl Foo for Bar { +} + +fn bb(r: R) -> Box { + Box::new(Bar(r)) //~ ERROR the parameter type `R` may not live long enough +} + +fn cc(r: R) -> Box { //~ ERROR missing lifetime specifier + Box::new(Bar(r)) +} + +// #54753 +pub struct Qux(T); + +pub struct Bazzzz(T); + +pub trait Baz {} +impl Baz for Bazzzz {} + +impl Qux { + fn baz(self) -> Box { + 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); +} diff --git a/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.stderr b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.stderr new file mode 100644 index 0000000000000..c8122dce19542 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/implicit-static-lifetime-in-dyn-trait-return-type.stderr @@ -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) -> Box { + | ^^ 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) -> Box { +LL + fn cc(r: R) -> Box { + | +help: instead, you are more likely to want to change the argument to be borrowed + | +LL | fn cc(r: &R) -> Box { + | + + +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) -> Box { + | ------- 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: R) -> Box { + | +++++++++ + +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 { + | ------- 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 Qux { + | +++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0310. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr index 62943616e3ad0..0c331355407de 100644 --- a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr +++ b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr @@ -38,6 +38,8 @@ LL | fn without_sized &'static (dyn std::fmt::Debug) + ?Sized>() {} error[E0310]: the parameter type `impl FnOnce(T) -> dyn Future` may not live long enough --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:6:5 | +LL | ) -> Box dyn Future> { + | ---------------------------------------- this `dyn Trait` has an implicit `'static` lifetime bound LL | Box::new(executor) | ^^^^^^^^^^^^^^^^^^ | |