Change:
Following the improvement for the diagnostic of the error reported in this issue , it would be nice (depending on how is prioritized) to have the same error message when instead of returning the function returns . When is returned I get a nice error message (on rustc 1.47): But if is used I get: with no suggestion to spell the type.
remove-assignment feel free to re-claim if you are working on this.

Discussion:
use rustc_errors::{Applicability, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; <ins> use rustc_hir::intravisit::Visitor; </ins> use rustc_hir::lang_items::LangItem; <del> use rustc_hir::{ItemKind, Node}; </del> <ins> use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; </ins> use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable;

} } <del> #[derive(Debug)] </del> struct ProhibitOpaqueVisitor<'tcx> { opaque_identity_ty: Ty<'tcx>, generics: &'tcx ty::Generics, <ins> tcx: TyCtxt<'tcx>, selftys: Vec<(Span, Option<String>)>, </ins> } impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {

} } <ins> impl Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { type Map = rustc_middle::hir::map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> { hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { match arg.kind { hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { [PathSegment { res: Some(Res::SelfTy(_, impl_ref)), .. }] => { let impl_ty_name = impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id)); self.selftys.push((path.span, impl_ty_name)); } _ => {} }, _ => {} } hir::intravisit::walk_ty(self, arg); } } </ins> if let ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, ..

InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), ), generics: tcx.generics_of(def_id), <ins> tcx, selftys: vec![], </ins> }; let prohibit_opaque = tcx .explicit_item_bounds(def_id) .iter() .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); debug!( <del> "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}", prohibit_opaque, visitor </del> <ins> "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics={:?}", prohibit_opaque, visitor.opaque_identity_ty, visitor.generics </ins> ); if let Some(ty) = prohibit_opaque.break_value() { <ins> visitor.visit_item(&item); </ins> let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { matches!(origin, hir::OpaqueTyOrigin::AsyncFn)

if is_async { "async fn" } else { "impl Trait" }, ); <del> if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) { if snippet == "Self" { err.span_suggestion( span, "consider spelling out the type instead", format!("{:?}", ty), Applicability::MaybeIncorrect, ); } </del> <ins> for (span, name) in visitor.selftys { err.span_suggestion( span, "consider spelling out the type instead", name.unwrap_or_else(|| format!("{:?}", ty)), Applicability::MaybeIncorrect, ); </ins> } err.emit(); }

<ins> // edition:2018 struct S<'a>(&'a i32); impl<'a> S<'a> { async fn new(i: &'a i32) -> Result<Self, ()> { //~^ ERROR: `async fn` Ok(S(&22)) } } fn main() {} </ins>

<ins> error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope --> $DIR/issue-78600.rs:6:33 | LL |     async fn new(i: &'a i32) -> Result<Self, ()> { |                                 ^^^^^^^----^^^^^ |                                        | |                                        help: consider spelling out the type instead: `S<'a>` error: aborting due to previous error For more information about this error, try `rustc --explain E0760`. </ins>