From 7868d20bd585906c19557ae7221ae5cc74a8f5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 4 Nov 2025 18:11:51 +0000 Subject: [PATCH] Account for `async fn` with `dyn Trait` return type in `impl Trait` suggestion --- .../src/error_reporting/traits/suggestions.rs | 16 +++++++++++++++- .../async-fn/dyn-in-return-type.stderr | 13 +++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 1094f00e42f2..16bb4c186447 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1891,7 +1891,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.primary_message("return type cannot be a trait object without pointer indirection"); err.children.clear(); - let span = obligation.cause.span; + let mut span = obligation.cause.span; + if let DefKind::Closure = self.tcx.def_kind(obligation.cause.body_id) + && let parent = self.tcx.parent(obligation.cause.body_id.into()) + && let DefKind::Fn = self.tcx.def_kind(parent) + && self.tcx.asyncness(parent).is_async() + && let Some(parent) = parent.as_local() + && let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. }) = + self.tcx.hir_node_by_def_id(parent) + { + // Do not suggest (#147894) + // async fn foo() -> dyn Display impl { .. } + // and + // async fn foo() -> dyn Display Box + span = fn_sig.decl.output.span(); + } let body = self.tcx.hir_body_owned_by(obligation.cause.body_id); let mut visitor = ReturnsVisitor::default(); diff --git a/tests/ui/async-await/async-fn/dyn-in-return-type.stderr b/tests/ui/async-await/async-fn/dyn-in-return-type.stderr index 6b1b092f5555..bd2ee4c208ca 100644 --- a/tests/ui/async-await/async-fn/dyn-in-return-type.stderr +++ b/tests/ui/async-await/async-fn/dyn-in-return-type.stderr @@ -9,16 +9,13 @@ LL | | } | help: consider returning an `impl Trait` instead of a `dyn Trait` | -LL | async fn f() -> dyn core::fmt::Debug impl { - | ++++ +LL - async fn f() -> dyn core::fmt::Debug { +LL + async fn f() -> impl core::fmt::Debug { + | help: alternatively, box the return type, and wrap all of the returned values in `Box::new` | -LL ~ async fn f() -> dyn core::fmt::Debug Box - | +LL | async fn f() -> Box { + | ++++ + error: aborting due to 1 previous error