about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir/src/hir.rs15
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs31
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs109
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs19
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs91
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs18
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs2
-rw-r--r--src/test/ui/async-await/issue-76547.stderr14
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.stderr6
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr5
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr21
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.stderr54
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.stderr54
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.stderr45
-rw-r--r--src/test/ui/self/elision/ref-self-async.stderr63
-rw-r--r--src/test/ui/self/elision/ref-struct-async.stderr45
17 files changed, 244 insertions, 350 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 43aa0ae265a..a9dbdd483fe 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2726,6 +2726,10 @@ pub struct FnHeader {
 }
 
 impl FnHeader {
+    pub fn is_async(&self) -> bool {
+        matches!(&self.asyncness, IsAsync::Async)
+    }
+
     pub fn is_const(&self) -> bool {
         matches!(&self.constness, Constness::Const)
     }
@@ -3169,7 +3173,7 @@ impl<'hir> Node<'hir> {
         }
     }
 
-    pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
+    pub fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> {
         match self {
             Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
@@ -3181,6 +3185,15 @@ impl<'hir> Node<'hir> {
         }
     }
 
+    pub fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> {
+        match self {
+            Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig),
+            _ => None,
+        }
+    }
+
     pub fn body_id(&self) -> Option<BodyId> {
         match self {
             Node::TraitItem(TraitItem {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index e98b9c3b03c..14ab635a2ae 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -65,11 +65,11 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Item, ItemKind, Node};
 use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{
     self,
+    error::TypeError,
     subst::{GenericArgKind, Subst, SubstsRef},
-    Region, Ty, TyCtxt, TypeFoldable,
+    Binder, Region, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
 use rustc_target::spec::abi;
@@ -1765,7 +1765,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.note_error_origin(diag, cause, exp_found, terr);
     }
 
-    pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+    pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
         if let ty::Opaque(def_id, substs) = ty.kind() {
             let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
             // Future::Output
@@ -1775,13 +1775,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
             for (predicate, _) in bounds {
                 let predicate = predicate.subst(self.tcx, substs);
-                if let ty::PredicateKind::Projection(projection_predicate) =
-                    predicate.kind().skip_binder()
-                {
-                    if projection_predicate.projection_ty.item_def_id == item_def_id {
-                        // We don't account for multiple `Future::Output = Ty` contraints.
-                        return projection_predicate.term.ty();
-                    }
+                let output = predicate
+                    .kind()
+                    .map_bound(|kind| match kind {
+                        ty::PredicateKind::Projection(projection_predicate)
+                            if projection_predicate.projection_ty.item_def_id == item_def_id =>
+                        {
+                            projection_predicate.term.ty()
+                        }
+                        _ => None,
+                    })
+                    .transpose();
+                if output.is_some() {
+                    // We don't account for multiple `Future::Output = Ty` contraints.
+                    return output;
                 }
             }
         }
@@ -1823,8 +1830,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
 
         match (
-            self.get_impl_future_output_ty(exp_found.expected),
-            self.get_impl_future_output_ty(exp_found.found),
+            self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder),
+            self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder),
         ) {
             (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() {
                 ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index ac57796763f..4eec492b3ae 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -106,90 +106,47 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             None => String::new(),
         };
 
-        let (span_1, span_2, main_label, span_label, future_return_type) =
-            match (sup_is_ret_type, sub_is_ret_type) {
-                (None, None) => {
-                    let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
-                        (
-                            "this type is declared with multiple lifetimes...".to_owned(),
-                            "...but data with one lifetime flows into the other here".to_owned(),
-                        )
-                    } else {
-                        (
-                            "these two types are declared with different lifetimes...".to_owned(),
-                            format!("...but data{} flows{} here", span_label_var1, span_label_var2),
-                        )
-                    };
-                    (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None)
-                }
+        debug!(
+            "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}",
+            sub_is_ret_type, sup_is_ret_type
+        );
 
-                (Some(ret_span), _) => {
-                    let sup_future = self.future_return_type(scope_def_id_sup);
-                    let (return_type, action) = if sup_future.is_some() {
-                        ("returned future", "held across an await point")
-                    } else {
-                        ("return type", "returned")
-                    };
+        let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
 
-                    (
-                        ty_sub.span,
-                        ret_span,
-                        format!(
-                            "this parameter and the {} are declared with different lifetimes...",
-                            return_type
-                        ),
-                        format!("...but data{} is {} here", span_label_var1, action),
-                        sup_future,
-                    )
-                }
-                (_, Some(ret_span)) => {
-                    let sub_future = self.future_return_type(scope_def_id_sub);
-                    let (return_type, action) = if sub_future.is_some() {
-                        ("returned future", "held across an await point")
-                    } else {
-                        ("return type", "returned")
-                    };
+        match (sup_is_ret_type, sub_is_ret_type) {
+            (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => {
+                let param_span =
+                    if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span };
+
+                err.span_label(
+                    param_span,
+                    "this parameter and the return type are declared with different lifetimes...",
+                );
+                err.span_label(ret_span, "");
+                err.span_label(span, format!("...but data{} is returned here", span_label_var1));
+            }
 
-                    (
+            (None, None) => {
+                if ty_sup.hir_id == ty_sub.hir_id {
+                    err.span_label(ty_sup.span, "this type is declared with multiple lifetimes...");
+                    err.span_label(ty_sub.span, "");
+                    err.span_label(span, "...but data with one lifetime flows into the other here");
+                } else {
+                    err.span_label(
                         ty_sup.span,
-                        ret_span,
-                        format!(
-                            "this parameter and the {} are declared with different lifetimes...",
-                            return_type
-                        ),
-                        format!("...but data{} is {} here", span_label_var1, action),
-                        sub_future,
-                    )
+                        "these two types are declared with different lifetimes...",
+                    );
+                    err.span_label(ty_sub.span, "");
+                    err.span_label(
+                        span,
+                        format!("...but data{} flows{} here", span_label_var1, span_label_var2),
+                    );
                 }
-            };
-
-        let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
-
-        err.span_label(span_1, main_label);
-        err.span_label(span_2, String::new());
-        err.span_label(span, span_label);
+            }
+        }
 
         self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
 
-        if let Some(t) = future_return_type {
-            let snip = self
-                .tcx()
-                .sess
-                .source_map()
-                .span_to_snippet(t.span)
-                .ok()
-                .and_then(|s| match (&t.kind, s.as_str()) {
-                    (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()),
-                    (_, "") => None,
-                    _ => Some(s),
-                })
-                .unwrap_or_else(|| "{unnamed_type}".to_string());
-
-            err.span_label(
-                t.span,
-                &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
-            );
-        }
         err.emit();
         Some(ErrorReported)
     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 07bba000566..b1535701bb3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -1,6 +1,5 @@
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::Node;
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_lifetime as rl;
@@ -25,25 +24,19 @@ pub(crate) fn find_anon_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     region: Region<'tcx>,
     br: &ty::BoundRegionKind,
-) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnDecl<'tcx>)> {
+) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> {
     if let Some(anon_reg) = tcx.is_suitable_region(region) {
         let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
-        let fndecl = match tcx.hir().get(hir_id) {
-            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
-            | Node::TraitItem(&hir::TraitItem {
-                kind: hir::TraitItemKind::Fn(ref m, ..), ..
-            })
-            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => {
-                &m.decl
-            }
-            _ => return None,
+        let Some(fn_sig) = tcx.hir().get(hir_id).fn_sig() else {
+            return None
         };
 
-        fndecl
+        fn_sig
+            .decl
             .inputs
             .iter()
             .find_map(|arg| find_component_for_bound_region(tcx, arg, br))
-            .map(|ty| (ty, &**fndecl))
+            .map(|ty| (ty, fn_sig))
     } else {
         None
     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index 3fa71d1a3d8..6d71d702cc8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -4,7 +4,7 @@
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::{self, DefIdTree, Region, Ty};
+use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable};
 use rustc_span::Span;
 
 /// Information about the anonymous region we are searching for.
@@ -94,81 +94,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             })
     }
 
-    pub(super) fn future_return_type(
-        &self,
-        local_def_id: LocalDefId,
-    ) -> Option<&rustc_hir::Ty<'_>> {
-        if let Some(hir::IsAsync::Async) = self.asyncness(local_def_id) {
-            if let rustc_middle::ty::Opaque(def_id, _) =
-                self.tcx().type_of(local_def_id).fn_sig(self.tcx()).output().skip_binder().kind()
-            {
-                match self.tcx().hir().get_if_local(*def_id) {
-                    Some(hir::Node::Item(hir::Item {
-                        kind:
-                            hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                bounds,
-                                origin: hir::OpaqueTyOrigin::AsyncFn(..),
-                                ..
-                            }),
-                        ..
-                    })) => {
-                        for b in bounds.iter() {
-                            if let hir::GenericBound::LangItemTrait(
-                                hir::LangItem::Future,
-                                _span,
-                                _hir_id,
-                                generic_args,
-                            ) = b
-                            {
-                                for type_binding in generic_args.bindings.iter() {
-                                    if type_binding.ident.name == rustc_span::sym::Output {
-                                        if let hir::TypeBindingKind::Equality {
-                                            term: hir::Term::Ty(ty),
-                                        } = type_binding.kind
-                                        {
-                                            return Some(ty);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    _ => {}
-                }
-            }
-        }
-        None
-    }
-
-    pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option<hir::IsAsync> {
-        // similar to the asyncness fn in rustc_ty_utils::ty
-        let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id);
-        let node = self.tcx().hir().get(hir_id);
-        let fn_kind = node.fn_kind()?;
-        Some(fn_kind.asyncness())
-    }
-
     // Here, we check for the case where the anonymous region
-    // is in the return type.
+    // is in the return type as written by the user.
     // FIXME(#42703) - Need to handle certain cases here.
     pub(super) fn is_return_type_anon(
         &self,
         scope_def_id: LocalDefId,
         br: ty::BoundRegionKind,
-        decl: &hir::FnDecl<'_>,
+        hir_sig: &hir::FnSig<'_>,
     ) -> Option<Span> {
-        let ret_ty = self.tcx().type_of(scope_def_id);
-        if let ty::FnDef(_, _) = ret_ty.kind() {
-            let sig = ret_ty.fn_sig(self.tcx());
-            let late_bound_regions =
-                self.tcx().collect_referenced_late_bound_regions(&sig.output());
-            if late_bound_regions.iter().any(|r| *r == br) {
-                return Some(decl.output.span());
-            }
+        let fn_ty = self.tcx().type_of(scope_def_id);
+        if let ty::FnDef(_, _) = fn_ty.kind() {
+            let ret_ty = fn_ty.fn_sig(self.tcx()).output();
+            let span = hir_sig.decl.output.span();
+            let future_output = if hir_sig.header.is_async() {
+                ret_ty.map_bound(|ty| self.infcx.get_impl_future_output_ty(ty)).transpose()
+            } else {
+                None
+            };
+            return match future_output {
+                Some(output) if self.includes_region(output, br) => Some(span),
+                None if self.includes_region(ret_ty, br) => Some(span),
+                _ => None,
+            };
         }
         None
     }
 
+    fn includes_region(
+        &self,
+        ty: Binder<'tcx, impl TypeFoldable<'tcx>>,
+        region: ty::BoundRegionKind,
+    ) -> bool {
+        let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty);
+        late_bound_regions.iter().any(|r| *r == region)
+    }
+
     // Here we check for the case where anonymous region
     // corresponds to self and if yes, we display E0312.
     // FIXME(#42700) - Need to format self properly to
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 3e73cc659ec..f6abeff60cd 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1909,7 +1909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => return,
         };
         let mut add_label = true;
-        if let ty::Adt(def, _) = output_ty.kind() {
+        if let ty::Adt(def, _) = output_ty.skip_binder().kind() {
             // no field access on enum type
             if !def.is_enum() {
                 if def
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 473c848ad8f..be4c9ec99b9 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -609,14 +609,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
             let ty = self.normalize_associated_types_in(expr.span, ty);
             let ty = match self.tcx.asyncness(fn_id.owner) {
-                hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| {
-                    infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
-                        span_bug!(
-                            fn_decl.output.span(),
-                            "failed to get output type of async function"
-                        )
+                hir::IsAsync::Async => self
+                    .tcx
+                    .infer_ctxt()
+                    .enter(|infcx| {
+                        infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
+                            span_bug!(
+                                fn_decl.output.span(),
+                                "failed to get output type of async function"
+                            )
+                        })
                     })
-                }),
+                    .skip_binder(),
                 hir::IsAsync::NotAsync => ty,
             };
             if self.can_coerce(found, ty) {
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 56f4d5afe40..96ab800afaf 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1274,7 +1274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
     ) {
         let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
-            Some(output_ty) => self.resolve_vars_if_possible(output_ty),
+            Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
             _ => return,
         };
         let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
diff --git a/src/test/ui/async-await/issue-76547.stderr b/src/test/ui/async-await/issue-76547.stderr
index 9bfb0f28028..ac5f99970c8 100644
--- a/src/test/ui/async-await/issue-76547.stderr
+++ b/src/test/ui/async-await/issue-76547.stderr
@@ -2,23 +2,17 @@ error[E0623]: lifetime mismatch
   --> $DIR/issue-76547.rs:20:13
    |
 LL | async fn fut(bufs: &mut [&mut [u8]]) {
-   |                          ---------   -
-   |                          |           |
-   |                          |           this `async fn` implicitly returns an `impl Future<Output = ()>`
-   |                          this parameter and the returned future are declared with different lifetimes...
+   |                    ---------------- these two types are declared with different lifetimes...
 LL |     ListFut(bufs).await
-   |             ^^^^ ...but data from `bufs` is held across an await point here
+   |             ^^^^ ...but data from `bufs` flows into `bufs` here
 
 error[E0623]: lifetime mismatch
   --> $DIR/issue-76547.rs:34:14
    |
 LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
-   |                           ---------      ---
-   |                           |              |
-   |                           |              this `async fn` implicitly returns an `impl Future<Output = i32>`
-   |                           this parameter and the returned future are declared with different lifetimes...
+   |                     ---------------- these two types are declared with different lifetimes...
 LL |     ListFut2(bufs).await
-   |              ^^^^ ...but data from `bufs` is held across an await point here
+   |              ^^^^ ...but data from `bufs` flows into `bufs` here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr
index ac29cca9d3f..8f602a1492a 100644
--- a/src/test/ui/async-await/issues/issue-63388-1.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-1.stderr
@@ -2,14 +2,12 @@ error[E0623]: lifetime mismatch
   --> $DIR/issue-63388-1.rs:14:9
    |
 LL |         &'a self, foo: &dyn Foo
-   |         -------- this parameter and the returned future are declared with different lifetimes...
+   |                        -------- this parameter and the return type are declared with different lifetimes...
 LL |     ) -> &dyn Foo
    |          --------
-   |          |
-   |          this `async fn` implicitly returns an `impl Future<Output = &dyn Foo>`
 LL |     {
 LL |         foo
-   |         ^^^ ...but data from `foo` is held across an await point here
+   |         ^^^ ...but data from `foo` is returned here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
index 464f283095d..149692a2c69 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -4,9 +4,8 @@ error[E0623]: lifetime mismatch
 LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
    |                                                      ------     ^^^^^^^^^^^^^^^^^^^
    |                                                      |          |
-   |                                                      |          ...but data from `a` is held across an await point here
-   |                                                      |          this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a> + 'b>`
-   |                                                      this parameter and the returned future are declared with different lifetimes...
+   |                                                      |          ...but data from `a` is returned here
+   |                                                      this parameter and the return type are declared with different lifetimes...
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
   --> $DIR/ret-impl-trait-one.rs:16:65
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
index e6846fb4049..299a2d2f2d3 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
@@ -2,28 +2,25 @@ error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
    |
 LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                          ----               ----   ^ ...but data from `f` is held across an await point here
-   |                          |                  |
-   |                          |                  this `async fn` implicitly returns an `impl Future<Output = &Foo>`
-   |                          this parameter and the returned future are declared with different lifetimes...
+   |                                    ----     ----   ^ ...but data from `f` is returned here
+   |                                    |
+   |                                    this parameter and the return type are declared with different lifetimes...
 
 error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:82
    |
 LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                          -----                        -----------------          ^ ...but data from `f` is held across an await point here
-   |                          |                            |
-   |                          |                            this `async fn` implicitly returns an `impl Future<Output = (Pin<&Foo>, &Foo)>`
-   |                          this parameter and the returned future are declared with different lifetimes...
+   |                                     ----              -----------------          ^ ...but data from `f` is returned here
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
 
 error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
    |
 LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |                                  -----                   ---   ^^^ ...but data from `arg` is held across an await point here
-   |                                  |                       |
-   |                                  |                       this `async fn` implicitly returns an `impl Future<Output = &()>`
-   |                                  this parameter and the returned future are declared with different lifetimes...
+   |                                               ------     ---   ^^^ ...but data from `arg` is returned here
+   |                                               |
+   |                                               this parameter and the return type are declared with different lifetimes...
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr
index 3221d270850..7448e8484b4 100644
--- a/src/test/ui/self/elision/lt-ref-self-async.stderr
+++ b/src/test/ui/self/elision/lt-ref-self-async.stderr
@@ -2,67 +2,61 @@ error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:13:9
    |
 LL |     async fn ref_self(&self, f: &u32) -> &u32 {
-   |                       -----              ----
-   |                       |                  |
-   |                       |                  this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                       this parameter and the returned future are declared with different lifetimes...
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:19:9
    |
 LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
-   |                             -----              ----
-   |                             |                  |
-   |                             |                  this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                             this parameter and the returned future are declared with different lifetimes...
+   |                                       ----     ----
+   |                                       |
+   |                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:23:9
    |
 LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-   |                                     -----               ----
-   |                                     |                   |
-   |                                     |                   this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                     this parameter and the returned future are declared with different lifetimes...
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:27:9
    |
 LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-   |                                     -----               ----
-   |                                     |                   |
-   |                                     |                   this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                     this parameter and the returned future are declared with different lifetimes...
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:31:9
    |
 LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-   |                                             -----                ----
-   |                                             |                    |
-   |                                             |                    this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                             this parameter and the returned future are declared with different lifetimes...
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self-async.rs:35:9
    |
 LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-   |                                         -----                ----
-   |                                         |                    |
-   |                                         |                    this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                         this parameter and the returned future are declared with different lifetimes...
+   |                                                     ----     ----
+   |                                                     |
+   |                                                     this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr
index b6ca986923d..6056cc46d3d 100644
--- a/src/test/ui/self/elision/ref-mut-self-async.stderr
+++ b/src/test/ui/self/elision/ref-mut-self-async.stderr
@@ -2,67 +2,61 @@ error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:13:9
    |
 LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
-   |                       ---------              ----
-   |                       |                      |
-   |                       |                      this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                       this parameter and the returned future are declared with different lifetimes...
+   |                                     ----     ----
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:19:9
    |
 LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
-   |                             ---------              ----
-   |                             |                      |
-   |                             |                      this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                             this parameter and the returned future are declared with different lifetimes...
+   |                                           ----     ----
+   |                                           |
+   |                                           this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:23:9
    |
 LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
-   |                                     ---------               ----
-   |                                     |                       |
-   |                                     |                       this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                     this parameter and the returned future are declared with different lifetimes...
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:27:9
    |
 LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
-   |                                     ---------               ----
-   |                                     |                       |
-   |                                     |                       this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                     this parameter and the returned future are declared with different lifetimes...
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:31:9
    |
 LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
-   |                                             ---------                ----
-   |                                             |                        |
-   |                                             |                        this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                             this parameter and the returned future are declared with different lifetimes...
+   |                                                             ----     ----
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self-async.rs:35:9
    |
 LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
-   |                                             ---------                ----
-   |                                             |                        |
-   |                                             |                        this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                             this parameter and the returned future are declared with different lifetimes...
+   |                                                             ----     ----
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr
index eda15d76390..61034ae4d47 100644
--- a/src/test/ui/self/elision/ref-mut-struct-async.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr
@@ -2,56 +2,51 @@ error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:13:9
    |
 LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
-   |                               -----------              ----
-   |                               |                        |
-   |                               |                        this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                               this parameter and the returned future are declared with different lifetimes...
+   |                                               ----     ----
+   |                                               |
+   |                                               this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:17:9
    |
 LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
-   |                                       -----------               ----
-   |                                       |                         |
-   |                                       |                         this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                       this parameter and the returned future are declared with different lifetimes...
+   |                                                        ----     ----
+   |                                                        |
+   |                                                        this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:21:9
    |
 LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
-   |                                       -----------               ----
-   |                                       |                         |
-   |                                       |                         this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                       this parameter and the returned future are declared with different lifetimes...
+   |                                                        ----     ----
+   |                                                        |
+   |                                                        this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:25:9
    |
 LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
-   |                                               -----------                ----
-   |                                               |                          |
-   |                                               |                          this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                               this parameter and the returned future are declared with different lifetimes...
+   |                                                                 ----     ----
+   |                                                                 |
+   |                                                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct-async.rs:29:9
    |
 LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
-   |                                               -----------                ----
-   |                                               |                          |
-   |                                               |                          this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                               this parameter and the returned future are declared with different lifetimes...
+   |                                                                 ----     ----
+   |                                                                 |
+   |                                                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr
index b42caa88c6f..0eab16e685d 100644
--- a/src/test/ui/self/elision/ref-self-async.stderr
+++ b/src/test/ui/self/elision/ref-self-async.stderr
@@ -2,78 +2,71 @@ error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:23:9
    |
 LL |     async fn ref_self(&self, f: &u32) -> &u32 {
-   |                       -----              ----
-   |                       |                  |
-   |                       |                  this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                       this parameter and the returned future are declared with different lifetimes...
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:29:9
    |
 LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
-   |                             -----              ----
-   |                             |                  |
-   |                             |                  this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                             this parameter and the returned future are declared with different lifetimes...
+   |                                       ----     ----
+   |                                       |
+   |                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:33:9
    |
 LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
-   |                                     -----               ----
-   |                                     |                   |
-   |                                     |                   this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                     this parameter and the returned future are declared with different lifetimes...
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:37:9
    |
 LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
-   |                                     -----               ----
-   |                                     |                   |
-   |                                     |                   this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                     this parameter and the returned future are declared with different lifetimes...
+   |                                                ----     ----
+   |                                                |
+   |                                                this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:41:9
    |
 LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
-   |                                             -----                ----
-   |                                             |                    |
-   |                                             |                    this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                             this parameter and the returned future are declared with different lifetimes...
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:45:9
    |
 LL |     async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
-   |                                             -----                ----
-   |                                             |                    |
-   |                                             |                    this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                             this parameter and the returned future are declared with different lifetimes...
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self-async.rs:49:9
    |
 LL |     async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
-   |                                            -----                    ---
-   |                                            |                        |
-   |                                            |                        this `async fn` implicitly returns an `impl Future<Output = &u8>`
-   |                                            this parameter and the returned future are declared with different lifetimes...
+   |                                                             ---     ---
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr
index 599becd3080..aa1d7453e83 100644
--- a/src/test/ui/self/elision/ref-struct-async.stderr
+++ b/src/test/ui/self/elision/ref-struct-async.stderr
@@ -2,56 +2,51 @@ error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:13:9
    |
 LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
-   |                               -------              ----
-   |                               |                    |
-   |                               |                    this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                               this parameter and the returned future are declared with different lifetimes...
+   |                                           ----     ----
+   |                                           |
+   |                                           this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:17:9
    |
 LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
-   |                                       -------               ----
-   |                                       |                     |
-   |                                       |                     this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                       this parameter and the returned future are declared with different lifetimes...
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:21:9
    |
 LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
-   |                                       -------               ----
-   |                                       |                     |
-   |                                       |                     this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                       this parameter and the returned future are declared with different lifetimes...
+   |                                                    ----     ----
+   |                                                    |
+   |                                                    this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:25:9
    |
 LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
-   |                                               -------                ----
-   |                                               |                      |
-   |                                               |                      this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                               this parameter and the returned future are declared with different lifetimes...
+   |                                                             ----     ----
+   |                                                             |
+   |                                                             this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct-async.rs:29:9
    |
 LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
-   |                                           -------                ----
-   |                                           |                      |
-   |                                           |                      this `async fn` implicitly returns an `impl Future<Output = &u32>`
-   |                                           this parameter and the returned future are declared with different lifetimes...
+   |                                                         ----     ----
+   |                                                         |
+   |                                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
-   |         ^ ...but data from `f` is held across an await point here
+   |         ^ ...but data from `f` is returned here
 
 error: aborting due to 5 previous errors