diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 1bc9f8cf3cc..881ebed6029 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -368,6 +368,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
                 error_region,
                 cause.clone(),
                 placeholder_region,
+                vec![],
             ),
         ),
         (Some(error_region), _) => NiceRegionError::new(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 85226e60bdb..c3f2213229a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -384,6 +384,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         sub_r,
                         sup_origin,
                         sup_r,
+                        _,
                     ) => {
                         if sub_r.is_placeholder() {
                             self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
@@ -464,7 +465,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         errors.sort_by_key(|u| match *u {
             RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
             RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
-            RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
+            RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
             RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
         });
         errors
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
index 6a330977002..fd295b74342 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
@@ -67,7 +67,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
     pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
         match (&self.error, self.regions) {
             (Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), sub, sup)),
-            (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => {
+            (Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
                 Some((origin.span(), sub, sup))
             }
             (None, Some((span, sub, sup))) => Some((span, sub, sup)),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 4aecc2f40b8..1a4a2803821 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -34,6 +34,7 @@ impl NiceRegionError<'me, 'tcx> {
                 sub_placeholder @ ty::RePlaceholder(_),
                 _,
                 sup_placeholder @ ty::RePlaceholder(_),
+                _,
             )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
@@ -49,6 +50,7 @@ impl NiceRegionError<'me, 'tcx> {
                 sub_placeholder @ ty::RePlaceholder(_),
                 _,
                 _,
+                _,
             )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
@@ -64,6 +66,7 @@ impl NiceRegionError<'me, 'tcx> {
                 _,
                 _,
                 sup_placeholder @ ty::RePlaceholder(_),
+                _,
             )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
@@ -79,6 +82,7 @@ impl NiceRegionError<'me, 'tcx> {
                 _,
                 SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ ty::RePlaceholder(_),
+                _,
             )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 2aaebed28ce..c7ba5087b8c 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -23,7 +23,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
         debug!("try_report_static_impl_trait(error={:?})", self.error);
         let tcx = self.tcx();
-        let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? {
+        let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? {
             RegionResolutionError::SubSupConflict(
                 _,
                 var_origin,
@@ -31,8 +31,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 sub_r,
                 sup_origin,
                 sup_r,
+                spans,
             ) if **sub_r == RegionKind::ReStatic => {
-                (var_origin, sub_origin, sub_r, sup_origin, sup_r)
+                (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans)
             }
             RegionResolutionError::ConcreteFailure(
                 SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
@@ -123,15 +124,31 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             param_name,
             lifetime,
         );
-        err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
+
+        let (mention_capture, capture_point) = if sup_origin.span().overlaps(param.param_ty_span) {
+            // Account for `async fn` like in `async-await/issues/issue-62097.rs`.
+            // The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same
+            // place (but with different `ctxt`, hence `overlaps` instead of `==` above).
+            //
+            // This avoids the following:
+            //
+            // LL |     pub async fn run_dummy_fn(&self) {
+            //    |                               ^^^^^
+            //    |                               |
+            //    |                               this data with an anonymous lifetime `'_`...
+            //    |                               ...is captured here...
+            (false, sup_origin.span())
+        } else {
+            (true, param.param_ty_span)
+        };
+        err.span_label(capture_point, &format!("this data with {}...", lifetime));
+
         debug!("try_report_static_impl_trait: param_info={:?}", param);
 
         // We try to make the output have fewer overlapping spans if possible.
         if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
             && sup_origin.span() != return_sp
         {
-            // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
-
             // Customize the spans and labels depending on their relative order so
             // that split sentences flow correctly.
             if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
@@ -152,11 +169,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 //    |           ----                               ^
                 err.span_label(
                     sup_origin.span(),
-                    "...is captured here, requiring it to live as long as `'static`",
+                    &format!(
+                        "...is captured here, requiring it to live as long as `'static`{}",
+                        if spans.is_empty() { "" } else { "..." },
+                    ),
                 );
             } else {
-                err.span_label(sup_origin.span(), "...is captured here...");
-                if return_sp < sup_origin.span() {
+                if return_sp < sup_origin.span() && mention_capture {
+                    err.span_label(sup_origin.span(), "...is captured here...");
                     err.span_note(
                         return_sp,
                         "...and is required to live as long as `'static` here",
@@ -164,17 +184,46 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 } else {
                     err.span_label(
                         return_sp,
-                        "...and is required to live as long as `'static` here",
+                        &format!(
+                            "...is required to live as long as `'static` here{}",
+                            if spans.is_empty() { "" } else { "..." },
+                        ),
                     );
+                    if mention_capture {
+                        let span = sup_origin.span();
+                        let msg = if spans.iter().any(|sp| *sp > span) {
+                            "...is captured here..."
+                        } else {
+                            "...and is captured here"
+                        };
+                        err.span_label(span, msg);
+                    }
                 }
             }
         } else {
             err.span_label(
                 return_sp,
-                "...is captured and required to live as long as `'static` here",
+                &format!(
+                    "...is captured and required to live as long as `'static` here{}",
+                    if spans.is_empty() { "" } else { "..." },
+                ),
             );
         }
 
+        for span in spans {
+            let msg =
+                format!("...and is captured here{}", if mention_capture { " too" } else { "" });
+            if span.overlaps(return_sp) {
+                err.span_note(*span, &msg);
+            } else {
+                err.span_label(*span, &msg);
+            }
+        }
+
+        if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
+            err.span_note(*bound, "`'static` lifetime requirement introduced by this trait bound");
+        }
+
         let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
 
         let mut override_error_code = None;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index cfa79213c80..452ca5eeabd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -28,6 +28,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             _sub,
             sup_origin,
             _sup,
+            _,
         ) = error.clone()
         {
             if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 4c9dcab26b1..14f6c72bb1c 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -19,6 +19,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
 use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
 use rustc_middle::ty::{Region, RegionVid};
+use rustc_span::Span;
 use std::fmt;
 
 /// This function performs lexical region resolution given a complete
@@ -96,6 +97,7 @@ pub enum RegionResolutionError<'tcx> {
         Region<'tcx>,
         SubregionOrigin<'tcx>,
         Region<'tcx>,
+        Vec<Span>,
     ),
 
     /// Indicates a `'b: 'a` constraint where `'a` is in a universe that
@@ -144,8 +146,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         let graph = self.construct_graph();
         self.expand_givens(&graph);
         self.expansion(&mut var_data);
-        self.collect_errors(&mut var_data, errors);
-        self.collect_var_errors(&var_data, &graph, errors);
+        let captures = self.collect_errors(&mut var_data, errors);
+        self.collect_var_errors(&var_data, &graph, errors, captures);
         var_data
     }
 
@@ -443,9 +445,16 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         &self,
         var_data: &mut LexicalRegionResolutions<'tcx>,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
-    ) {
+    ) -> Vec<Span> {
+        let mut captures = vec![];
+
         for (constraint, origin) in &self.data.constraints {
             debug!(?constraint, ?origin);
+            if let (Constraint::VarSubVar(_, _), SubregionOrigin::DataBorrowed(_, sp)) =
+                (constraint, origin)
+            {
+                captures.push(*sp);
+            }
             match *constraint {
                 Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
                     // Expansion will ensure that these constraints hold. Ignore.
@@ -515,6 +524,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 sub,
             ));
         }
+        captures
     }
 
     /// Go over the variables that were declared to be error variables
@@ -524,6 +534,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         var_data: &LexicalRegionResolutions<'tcx>,
         graph: &RegionGraph<'tcx>,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
+        captures: Vec<Span>,
     ) {
         debug!("collect_var_errors, var_data = {:#?}", var_data.values);
 
@@ -567,7 +578,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     // if this rule starts to create problems we'll
                     // have to revisit this portion of the code and
                     // think hard about it. =) -- nikomatsakis
-                    self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
+                    self.collect_error_for_expanding_node(
+                        graph,
+                        &mut dup_vec,
+                        node_vid,
+                        errors,
+                        &captures,
+                    );
                 }
             }
         }
@@ -621,6 +638,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
         node_idx: RegionVid,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
+        captures: &[Span],
     ) {
         // Errors in expanding nodes result from a lower-bound that is
         // not contained by an upper-bound.
@@ -667,6 +685,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                          sup: {:?}",
                         origin, node_idx, lower_bound.region, upper_bound.region
                     );
+
+                    let mut capture_spans: Vec<Span> = captures.iter().cloned().collect();
+                    // Below, one span expects `&Span` and the other `&mut Span`, hence the dupes.
+                    capture_spans.sort_by_key(|span| (span.lo(), span.hi()));
+                    capture_spans.dedup_by_key(|span| (span.lo(), span.hi()));
                     errors.push(RegionResolutionError::SubSupConflict(
                         node_idx,
                         origin,
@@ -674,6 +697,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                         lower_bound.region,
                         upper_bound.origin.clone(),
                         upper_bound.region,
+                        capture_spans,
                     ));
                     return;
                 }
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index 56a28d904b9..bb329a4a0c2 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -2,12 +2,20 @@ error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'
   --> $DIR/issue-62097.rs:12:31
    |
 LL |     pub async fn run_dummy_fn(&self) {
-   |                               ^^^^^
-   |                               |
-   |                               this data with an anonymous lifetime `'_`...
-   |                               ...is captured here...
+   |                               ^^^^^ this data with an anonymous lifetime `'_`...
 LL |         foo(|| self.bar()).await;
-   |         --- ...and is required to live as long as `'static` here
+   |         --- ...is required to live as long as `'static` here...
+   |
+note: ...and is captured here
+  --> $DIR/issue-62097.rs:13:9
+   |
+LL |         foo(|| self.bar()).await;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+note: `'static` lifetime requirement introduced by this trait bound
+  --> $DIR/issue-62097.rs:4:19
+   |
+LL |     F: FnOnce() + 'static
+   |                   ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/issues/issue-72312.rs b/src/test/ui/async-await/issues/issue-72312.rs
new file mode 100644
index 00000000000..d33685e02f1
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-72312.rs
@@ -0,0 +1,19 @@
+// edition:2018
+fn require_static<T: 'static>(val: T) -> T {
+    //~^ NOTE 'static` lifetime requirement introduced by this trait bound
+    val
+}
+
+struct Problem;
+
+impl Problem {
+    pub async fn start(&self) { //~ ERROR E0759
+        //~^ NOTE this data with an anonymous lifetime `'_`
+        //~| NOTE in this expansion of desugaring of `async` block or function
+        require_static(async move { //~ NOTE ...is required to live as long as `'static` here
+            &self; //~ NOTE ...and is captured here
+        });
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-72312.stderr b/src/test/ui/async-await/issues/issue-72312.stderr
new file mode 100644
index 00000000000..ee5ee6f0f93
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-72312.stderr
@@ -0,0 +1,20 @@
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/issue-72312.rs:10:24
+   |
+LL |     pub async fn start(&self) {
+   |                        ^^^^^ this data with an anonymous lifetime `'_`...
+...
+LL |         require_static(async move {
+   |         -------------- ...is required to live as long as `'static` here...
+LL |             &self;
+   |             ----- ...and is captured here
+   |
+note: `'static` lifetime requirement introduced by this trait bound
+  --> $DIR/issue-72312.rs:2:22
+   |
+LL | fn require_static<T: 'static>(val: T) -> T {
+   |                      ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs b/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs
index 9b27fd46f7a..95698fd1e1a 100644
--- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -29,4 +29,22 @@ fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
     y.get_b() // ERROR
 }
 
+fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+    <_ as Bar>::get_b(x) // ERROR
+    //~^ ERROR `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+}
+
+fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+    <_ as Bar<'_, '_>>::get_b(x) // ERROR
+    //~^ ERROR `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+}
+
+fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+    let y = x as &dyn Bar<'_, '_>;
+    //~^ ERROR `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+    y.get_b(); // ERROR
+    let z = y;
+    z.get_b() // ERROR
+}
+
 fn main() {}
diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr
index 4967f3dc2c8..04560ea4e29 100644
--- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -39,9 +39,53 @@ LL |     let y = x as &dyn Bar<'_, '_>;
    |             ...is captured here...
 LL |
 LL |     y.get_b() // ERROR
-   |     --------- ...and is required to live as long as `'static` here
+   |     --------- ...is required to live as long as `'static` here...
+   |
+note: ...and is captured here too
+  --> $DIR/type-checking-test-4.rs:29:5
+   |
+LL |     y.get_b() // ERROR
+   |     ^
 
-error: aborting due to 3 previous errors
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/type-checking-test-4.rs:33:5
+   |
+LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                       ------------ this data with lifetime `'a`...
+LL |     <_ as Bar>::get_b(x) // ERROR
+   |     ^^^^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static`
+
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/type-checking-test-4.rs:38:15
+   |
+LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                       ------------ this data with lifetime `'a`...
+LL |     <_ as Bar<'_, '_>>::get_b(x) // ERROR
+   |     ----------^^---------------- ...is captured and required to live as long as `'static` here
+
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/type-checking-test-4.rs:43:27
+   |
+LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                       ------------ this data with lifetime `'a`...
+LL |     let y = x as &dyn Bar<'_, '_>;
+   |             -             ^^
+   |             |
+   |             ...is captured here...
+LL |
+LL |     y.get_b(); // ERROR
+   |     - ...and is captured here too
+LL |     let z = y;
+LL |     z.get_b() // ERROR
+   |     --------- ...is required to live as long as `'static` here...
+   |
+note: ...and is captured here too
+  --> $DIR/type-checking-test-4.rs:47:5
+   |
+LL |     z.get_b() // ERROR
+   |     ^
+
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0308, E0759.
 For more information about an error, try `rustc --explain E0308`.