about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-12-11 17:35:23 +0100
committerGitHub <noreply@github.com>2021-12-11 17:35:23 +0100
commit7bba5c163c3530d3eeab03128bd1c72d331a16df (patch)
treed034c2d3ce35992fd3c49b376340f3ad1390046c
parent433a13b47347849dbc8c5d5300b98b95be7fb2c9 (diff)
parentd2d9eb3715e61d16eafb55b4b8cb03fdc6bfc871 (diff)
downloadrust-7bba5c163c3530d3eeab03128bd1c72d331a16df.tar.gz
rust-7bba5c163c3530d3eeab03128bd1c72d331a16df.zip
Rollup merge of #89734 - estebank:issue-72312, r=nikomatsakis
Point at capture points for non-`'static` reference crossing a `yield` point

```
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`.
```

Fix #72312.
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs139
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs1
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs30
-rw-r--r--compiler/rustc_middle/src/ty/context.rs36
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs20
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr2
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr11
-rw-r--r--src/test/ui/async-await/issues/issue-62097.stderr13
-rw-r--r--src/test/ui/async-await/issues/issue-72312.nll.stderr21
-rw-r--r--src/test/ui/async-await/issues/issue-72312.rs19
-rw-r--r--src/test/ui/async-await/issues/issue-72312.stderr23
-rw-r--r--src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr7
-rw-r--r--src/test/ui/generator/generator-region-requirements.stderr2
-rw-r--r--src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr12
-rw-r--r--src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr2
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr44
-rw-r--r--src/test/ui/issues/issue-16922.stderr2
-rw-r--r--src/test/ui/issues/issue-46983.stderr2
-rw-r--r--src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr2
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr2
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr10
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.stderr21
-rw-r--r--src/test/ui/regions/regions-addr-of-self.stderr2
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.stderr9
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.stderr9
-rw-r--r--src/test/ui/regions/regions-proc-bound-capture.stderr10
-rw-r--r--src/test/ui/regions/regions-static-bound.stderr4
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr2
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr12
-rw-r--r--src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr8
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-4.rs18
-rw-r--r--src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr82
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr12
37 files changed, 466 insertions, 133 deletions
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..80d4a2e57da 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
@@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
 use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
 use rustc_middle::ty::{
-    self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
+    self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable,
+    TypeVisitor,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{MultiSpan, Span};
@@ -23,7 +24,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 +32,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, .. }),
@@ -74,7 +76,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     err.span_label(
                         cause.span,
                         &format!(
-                            "...is captured and required to live as long as `'static` here \
+                            "...is used and required to live as long as `'static` here \
                              because of an implicit lifetime bound on the {}",
                             match ctxt.assoc_item.container {
                                 AssocItemContainer::TraitContainer(id) =>
@@ -123,56 +125,101 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             param_name,
             lifetime,
         );
-        err.span_label(param.param_ty_span, &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() {
-                // Avoid the following:
-                //
-                // error: cannot infer an appropriate lifetime
-                //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
-                //    |
-                // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
-                //    |           ----                      ---------^-
+        let (mention_influencer, influencer_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).
                 //
-                // and instead show:
+                // This avoids the following:
                 //
-                // error: cannot infer an appropriate lifetime
-                //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
-                //    |
-                // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
-                //    |           ----                               ^
-                err.span_label(
-                    sup_origin.span(),
-                    "...is captured here, requiring it to live as long as `'static`",
-                );
+                // LL |     pub async fn run_dummy_fn(&self) {
+                //    |                               ^^^^^
+                //    |                               |
+                //    |                               this data with an anonymous lifetime `'_`...
+                //    |                               ...is captured here...
+                (false, sup_origin.span())
             } else {
-                err.span_label(sup_origin.span(), "...is captured here...");
-                if return_sp < sup_origin.span() {
-                    err.span_note(
-                        return_sp,
-                        "...and is required to live as long as `'static` here",
+                (!sup_origin.span().overlaps(return_sp), param.param_ty_span)
+            };
+        err.span_label(influencer_point, &format!("this data with {}...", lifetime));
+
+        debug!("try_report_static_impl_trait: param_info={:?}", param);
+
+        let mut spans = spans.clone();
+
+        if mention_influencer {
+            spans.push(sup_origin.span());
+        }
+        // We dedup the spans *ignoring* expansion context.
+        spans.sort();
+        spans.dedup_by_key(|span| (span.lo(), span.hi()));
+
+        // We try to make the output have fewer overlapping spans if possible.
+        let require_msg = if spans.is_empty() {
+            "...is used and required to live as long as `'static` here"
+        } else {
+            "...and is required to live as long as `'static` here"
+        };
+        let require_span =
+            if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
+
+        for span in &spans {
+            err.span_label(*span, "...is used here...");
+        }
+
+        if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) {
+            // If any of the "captured here" labels appears on the same line or after
+            // `require_span`, we put it on a note to ensure the text flows by appearing
+            // always at the end.
+            err.span_note(require_span, require_msg);
+        } else {
+            // We don't need a note, it's already at the end, it can be shown as a `span_label`.
+            err.span_label(require_span, require_msg);
+        }
+
+        if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
+            err.span_note(*bound, "`'static` lifetime requirement introduced by this bound");
+        }
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
+            if let ObligationCauseCode::ReturnValue(hir_id)
+            | ObligationCauseCode::BlockTailExpression(hir_id) = &cause.code
+            {
+                let parent_id = tcx.hir().get_parent_item(*hir_id);
+                if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) {
+                    let mut span: MultiSpan = fn_decl.output.span().into();
+                    let mut add_label = true;
+                    if let hir::FnRetTy::Return(ty) = fn_decl.output {
+                        let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
+                        v.visit_ty(ty);
+                        if !v.0.is_empty() {
+                            span = v.0.clone().into();
+                            for sp in v.0 {
+                                span.push_span_label(
+                                    sp,
+                                    "`'static` requirement introduced here".to_string(),
+                                );
+                            }
+                            add_label = false;
+                        }
+                    }
+                    if add_label {
+                        span.push_span_label(
+                            fn_decl.output.span(),
+                            "requirement introduced by this return type".to_string(),
+                        );
+                    }
+                    span.push_span_label(
+                        cause.span,
+                        "because of this returned expression".to_string(),
                     );
-                } else {
-                    err.span_label(
-                        return_sp,
-                        "...and is required to live as long as `'static` here",
+                    err.span_note(
+                        span,
+                        "`'static` lifetime requirement introduced by the return type",
                     );
                 }
             }
-        } else {
-            err.span_label(
-                return_sp,
-                "...is captured and required to live as long as `'static` here",
-            );
         }
 
         let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
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..85ee6d2cdc2 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>, // All the influences on a given value that didn't meet its constraints.
     ),
 
     /// Indicates a `'b: 'a` constraint where `'a` is in a universe that
@@ -567,7 +569,30 @@ 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);
+
+                    // Obtain the spans for all the places that can
+                    // influence the constraints on this value for
+                    // richer diagnostics in `static_impl_trait`.
+                    let influences: Vec<Span> = self
+                        .data
+                        .constraints
+                        .iter()
+                        .filter_map(|(constraint, origin)| match (constraint, origin) {
+                            (
+                                Constraint::VarSubVar(_, sup),
+                                SubregionOrigin::DataBorrowed(_, sp),
+                            ) if sup == &node_vid => Some(*sp),
+                            _ => None,
+                        })
+                        .collect();
+
+                    self.collect_error_for_expanding_node(
+                        graph,
+                        &mut dup_vec,
+                        node_vid,
+                        errors,
+                        influences,
+                    );
                 }
             }
         }
@@ -621,6 +646,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
         node_idx: RegionVid,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
+        influences: Vec<Span>,
     ) {
         // Errors in expanding nodes result from a lower-bound that is
         // not contained by an upper-bound.
@@ -667,6 +693,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                          sup: {:?}",
                         origin, node_idx, lower_bound.region, upper_bound.region
                     );
+
                     errors.push(RegionResolutionError::SubSupConflict(
                         node_idx,
                         origin,
@@ -674,6 +701,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                         lower_bound.region,
                         upper_bound.origin.clone(),
                         upper_bound.region,
+                        influences,
                     ));
                     return;
                 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 275a2128c45..0bf457ca8a8 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1481,40 +1481,8 @@ impl<'tcx> TyCtxt<'tcx> {
         scope_def_id: LocalDefId,
     ) -> Vec<&'tcx hir::Ty<'tcx>> {
         let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
-        let hir_output = match self.hir().get(hir_id) {
-            Node::Item(hir::Item {
-                kind:
-                    ItemKind::Fn(
-                        hir::FnSig {
-                            decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
-                            ..
-                        },
-                        ..,
-                    ),
-                ..
-            })
-            | Node::ImplItem(hir::ImplItem {
-                kind:
-                    hir::ImplItemKind::Fn(
-                        hir::FnSig {
-                            decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
-                            ..
-                        },
-                        _,
-                    ),
-                ..
-            })
-            | Node::TraitItem(hir::TraitItem {
-                kind:
-                    hir::TraitItemKind::Fn(
-                        hir::FnSig {
-                            decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
-                            ..
-                        },
-                        _,
-                    ),
-                ..
-            }) => ty,
+        let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) {
+            Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty,
             _ => return vec![],
         };
 
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 8803370251b..1acb3ec57de 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -6,6 +6,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
+use rustc_span::Span;
 
 impl<'tcx> TyS<'tcx> {
     /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive.
@@ -432,3 +433,22 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
         hir::intravisit::walk_ty(self, ty);
     }
 }
+
+/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
+pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>);
+
+impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
+    type Map = rustc_hir::intravisit::ErasedMap<'v>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+
+    fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
+        if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static =
+            lt.name
+        {
+            self.0.push(lt.span);
+        }
+    }
+}
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
index 0be9b37263a..33f1e0f05b2 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
@@ -4,7 +4,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
 LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
    |                  ------- this data with lifetime `'a`...
 LL |    bar(foo, x)
-   |    ----^^^---- ...is captured and required to live as long as `'static` here
+   |        ^^^  - ...is used and required to live as long as `'static` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
index 0a44864b249..609627aaa9e 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -5,7 +5,16 @@ LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
    |                   -------- this data with lifetime `'a`...
 ...
 LL |     bar(foo, x)
-   |     ----^^^---- ...is captured and required to live as long as `'static` here
+   |         ^^^  - ...is used and required to live as long as `'static` here
+   |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/project-fn-ret-invariant.rs:45:37
+   |
+LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
+   |                                     ^^^^^^^ `'static` requirement introduced here
+...
+LL |     bar(foo, x)
+   |     ----------- because of this returned expression
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index 56a28d904b9..e23277543c6 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -2,12 +2,15 @@ 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 used and required to live as long as `'static` here
+   |
+note: `'static` lifetime requirement introduced by this 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.nll.stderr b/src/test/ui/async-await/issues/issue-72312.nll.stderr
new file mode 100644
index 00000000000..068d8c64d68
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-72312.nll.stderr
@@ -0,0 +1,21 @@
+error[E0521]: borrowed data escapes outside of associated function
+  --> $DIR/issue-72312.rs:13:24
+   |
+LL |       pub async fn start(&self) {
+   |                          -----
+   |                          |
+   |                          `self` is a reference that is only valid in the associated function body
+   |                          let's call the lifetime of this reference `'1`
+...
+LL |           require_static(async move {
+   |  ________________________^
+LL | |             &self;
+LL | |         });
+   | |         ^
+   | |         |
+   | |_________`self` escapes the associated function body here
+   |           argument requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
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..eb7d12e290c
--- /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 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 ...and is required to live as long as `'static` here
+            &self; //~ NOTE ...is used 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..798f755765c
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-72312.stderr
@@ -0,0 +1,23 @@
+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 |             &self;
+   |             ----- ...is used here...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/issue-72312.rs:13:9
+   |
+LL |         require_static(async move {
+   |         ^^^^^^^^^^^^^^
+note: `'static` lifetime requirement introduced by this 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/closures/closure-bounds-static-cant-capture-borrowed.stderr b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr
index d761abdfc6a..af1f908a808 100644
--- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr
+++ b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr
@@ -8,13 +8,18 @@ LL |       bar(|| {
 LL | |
 LL | |         let _ = x;
 LL | |     })
-   | |_____^ ...is captured here...
+   | |_____^ ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
    |
 LL |     bar(|| {
    |     ^^^
+note: `'static` lifetime requirement introduced by this bound
+  --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:1:39
+   |
+LL | fn bar<F>(blk: F) where F: FnOnce() + 'static {
+   |                                       ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generator/generator-region-requirements.stderr b/src/test/ui/generator/generator-region-requirements.stderr
index b6b9db22426..30d67050b90 100644
--- a/src/test/ui/generator/generator-region-requirements.stderr
+++ b/src/test/ui/generator/generator-region-requirements.stderr
@@ -5,7 +5,7 @@ LL | fn dangle(x: &mut i32) -> &'static mut i32 {
    |              -------- this data with an anonymous lifetime `'_`...
 ...
 LL |         x
-   |         ^ ...is captured here...
+   |         ^ ...is used here...
 ...
 LL |             GeneratorState::Complete(c) => return c,
    |                                                   - ...and is required to live as long as `'static` here
diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr
index 1ffd205652f..32c5ccf1648 100644
--- a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr
+++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr
@@ -4,7 +4,9 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
    |         ------------------------------- this data with an anonymous lifetime `'_`...
 LL |     x.m()
-   |     --^-- ...is captured and required to live as long as `'static` here
+   |     - ^
+   |     |
+   |     ...is used and required to live as long as `'static` here
 
 error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/projection-type-lifetime-mismatch.rs:22:7
@@ -12,7 +14,9 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
    |                                       -- this data with an anonymous lifetime `'_`...
 LL |     x.m()
-   |     --^-- ...is captured and required to live as long as `'static` here
+   |     - ^
+   |     |
+   |     ...is used and required to live as long as `'static` here
 
 error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/projection-type-lifetime-mismatch.rs:27:7
@@ -20,7 +24,9 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn h(x: &()) -> &'static () {
    |         --- this data with an anonymous lifetime `'_`...
 LL |     x.m()
-   |     --^-- ...is captured and required to live as long as `'static` here
+   |     - ^
+   |     |
+   |     ...is used and required to live as long as `'static` here
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
index b3bef677d19..2307572cc3f 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -4,7 +4,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
    |                                 ------------------- this data with lifetime `'a`...
 LL |     static_val(x);
-   |                ^ ...is captured here...
+   |                ^ ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/dyn-trait.rs:20:5
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index d65dea7adc9..de5d3b612c9 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -28,7 +28,7 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
   --> $DIR/must_outlive_least_region_or_bound.rs:9:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
-   |               ----                           ^ ...is captured here...
+   |               ----                           ^ ...is used here...
    |               |
    |               this data with an anonymous lifetime `'_`...
    |
@@ -50,7 +50,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:11:55
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-   |                     -------                           ^ ...is captured here...
+   |                     -------                           ^ ...is used here...
    |                     |
    |                     this data with lifetime `'a`...
    |
@@ -80,7 +80,7 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
   --> $DIR/must_outlive_least_region_or_bound.rs:24:65
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
-   |               ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static`
+   |               ---- this data with an anonymous lifetime `'_`... ^ ...is used and required to live as long as `'static` here
    |
 help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
    |
@@ -95,7 +95,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:29:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                      ------- this data with lifetime `'a`...        ^ ...is captured here...
+   |                      ------- this data with lifetime `'a`...        ^ ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/must_outlive_least_region_or_bound.rs:29:34
@@ -136,10 +136,17 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
   --> $DIR/must_outlive_least_region_or_bound.rs:16:50
    |
 LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
-   |               ----                               ^ ...is captured here, requiring it to live as long as `'static`
+   |               ----                               ^ ...is used and required to live as long as `'static` here
    |               |
    |               this data with an anonymous lifetime `'_`...
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/must_outlive_least_region_or_bound.rs:16:28
+   |
+LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+   |                            ^^^^^^^^^    ----------- because of this returned expression
+   |                            |
+   |                            `'static` requirement introduced here
 help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
    |
 LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
@@ -149,10 +156,17 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:18:59
    |
 LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
-   |                     -------                               ^ ...is captured here, requiring it to live as long as `'static`
+   |                     -------                               ^ ...is used and required to live as long as `'static` here
    |                     |
    |                     this data with lifetime `'a`...
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/must_outlive_least_region_or_bound.rs:18:37
+   |
+LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
+   |                                     ^^^^^^^^^    ----------- because of this returned expression
+   |                                     |
+   |                                     `'static` requirement introduced here
 help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound
    |
 LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
@@ -162,10 +176,17 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
   --> $DIR/must_outlive_least_region_or_bound.rs:20:60
    |
 LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
-   |               ----                                         ^ ...is captured here, requiring it to live as long as `'static`
+   |               ----                                         ^ ...is used and required to live as long as `'static` here
    |               |
    |               this data with an anonymous lifetime `'_`...
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/must_outlive_least_region_or_bound.rs:20:40
+   |
+LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |                                        ^^^^^^^    ----------- because of this returned expression
+   |                                        |
+   |                                        `'static` requirement introduced here
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
@@ -179,8 +200,15 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:22:69
    |
 LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
-   |                     ------- this data with lifetime `'a`...         ^ ...is captured here, requiring it to live as long as `'static`
+   |                     ------- this data with lifetime `'a`...         ^ ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:49
+   |
+LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |                                                 ^^^^^^^    ----------- because of this returned expression
+   |                                                 |
+   |                                                 `'static` requirement introduced here
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 8b09b7d5907..53405a660f8 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -4,7 +4,7 @@ error[E0759]: `value` has an anonymous lifetime `'_` but it needs to satisfy a `
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
    |                       -- this data with an anonymous lifetime `'_`...
 LL |     Box::new(value) as Box<dyn Any>
-   |              ^^^^^ ...is captured here, requiring it to live as long as `'static`
+   |              ^^^^^ ...is used and required to live as long as `'static` here
    |
 help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound
    |
diff --git a/src/test/ui/issues/issue-46983.stderr b/src/test/ui/issues/issue-46983.stderr
index 77fb130f519..ed9f1884c42 100644
--- a/src/test/ui/issues/issue-46983.stderr
+++ b/src/test/ui/issues/issue-46983.stderr
@@ -4,7 +4,7 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn foo(x: &u32) -> &'static u32 {
    |           ---- this data with an anonymous lifetime `'_`...
 LL |     &*x
-   |     ^^^ ...is captured and required to live as long as `'static` here
+   |     ^^^ ...is used and required to live as long as `'static` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
index 3f65d3af725..e06255e4ea3 100644
--- a/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
+++ b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
@@ -4,7 +4,7 @@ error[E0759]: `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'s
 LL | fn inner(mut foo: &[u8]) {
    |                   ----- this data with an anonymous lifetime `'_`...
 LL |     let refcell = RefCell::new(&mut foo);
-   |                                ^^^^^^^^ ...is captured here...
+   |                                ^^^^^^^^ ...is used here...
 ...
 LL |     read_thing(read);
    |                ---- ...and is required to live as long as `'static` here
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 1931934a211..4a6378b84f1 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -4,7 +4,7 @@ error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'stati
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
    |               ------- this data with lifetime `'a`...
 LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |     ^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
index e0a8534cd28..1708700f77a 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
@@ -5,8 +5,16 @@ LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
    |             --------------- this data with an anonymous lifetime `'_`...
 ...
 LL |     ss.r
-   |     ^^^^ ...is captured and required to live as long as `'static` here
+   |     ^^^^ ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/object-lifetime-default-from-box-error.rs:14:37
+   |
+LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
+   |                                     ^^^^^^^^^^^^^ `'static` requirement introduced here
+...
+LL |     ss.r
+   |     ---- because of this returned expression
 help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> {
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 04d22e58a1d..d8932c067ac 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -4,7 +4,7 @@ error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
    |         ----- this data with an anonymous lifetime `'_`...
 LL |     let x: Box<dyn Foo + 'static> = Box::new(v);
-   |                                              ^ ...is captured here, requiring it to live as long as `'static`
+   |                                              ^ ...is used and required to live as long as `'static` here
    |
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
@@ -21,8 +21,15 @@ error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
    |         ----- this data with an anonymous lifetime `'_`...
 LL |     Box::new(v)
-   |              ^ ...is captured here, requiring it to live as long as `'static`
+   |              ^ ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/region-object-lifetime-in-coercion.rs:12:33
+   |
+LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
+   |                                 ^^^^^^^ `'static` requirement introduced here
+LL |     Box::new(v)
+   |     ----------- because of this returned expression
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + '_> {
@@ -39,8 +46,16 @@ LL | fn c(v: &[u8]) -> Box<dyn Foo> {
    |         ----- this data with an anonymous lifetime `'_`...
 ...
 LL |     Box::new(v)
-   |              ^ ...is captured here, requiring it to live as long as `'static`
+   |              ^ ...is used and required to live as long as `'static` here
+   |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/region-object-lifetime-in-coercion.rs:16:23
    |
+LL | fn c(v: &[u8]) -> Box<dyn Foo> {
+   |                       ^^^^^^^ `'static` requirement introduced here
+...
+LL |     Box::new(v)
+   |     ----------- because of this returned expression
 help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo + '_> {
diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr
index 738691fd695..3453c6458f1 100644
--- a/src/test/ui/regions/regions-addr-of-self.stderr
+++ b/src/test/ui/regions/regions-addr-of-self.stderr
@@ -4,7 +4,7 @@ error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'
 LL |     pub fn chase_cat(&mut self) {
    |                      --------- this data with an anonymous lifetime `'_`...
 LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 9a7df8c0188..4153f4f29bc 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -4,8 +4,15 @@ error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime
 LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
    |                         ------------------ this data with lifetime `'a`...
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |                ^^^ ...is captured here, requiring it to live as long as `'static`
+   |                ^^^ ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/regions-close-object-into-object-2.rs:8:60
+   |
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
+   |                                                            ^^^^^^^ `'static` requirement introduced here
+LL |     Box::new(B(&*v)) as Box<dyn X>
+   |     ------------------------------ because of this returned expression
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
 LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'a> {
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index a7a9b16b080..2ea4b431b38 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -4,8 +4,15 @@ error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime
 LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
    |                   ---------------- this data with lifetime `'a`...
 LL |     Box::new(B(&*v)) as Box<dyn X>
-   |                ^^^ ...is captured here, requiring it to live as long as `'static`
+   |                ^^^ ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/regions-close-object-into-object-4.rs:8:52
+   |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |                                                    ^^^^^^^ `'static` requirement introduced here
+LL |     Box::new(B(&*v)) as Box<dyn X>
+   |     ------------------------------ because of this returned expression
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
 LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'a> {
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index 50b3748bf40..2ebe874da93 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -5,8 +5,16 @@ LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
    |                   ------ this data with an anonymous lifetime `'_`...
 LL |     // This is illegal, because the region bound on `proc` is 'static.
 LL |     Box::new(move || { *x })
-   |              ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static`
+   |              ^^^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/regions-proc-bound-capture.rs:7:59
+   |
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+   |                                                           ^^^^^^^ `'static` requirement introduced here
+LL |     // This is illegal, because the region bound on `proc` is 'static.
+LL |     Box::new(move || { *x })
+   |     ------------------------ because of this returned expression
 help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + '_> {
diff --git a/src/test/ui/regions/regions-static-bound.stderr b/src/test/ui/regions/regions-static-bound.stderr
index 51fe16ca9da..b8e69e02609 100644
--- a/src/test/ui/regions/regions-static-bound.stderr
+++ b/src/test/ui/regions/regions-static-bound.stderr
@@ -17,7 +17,7 @@ error[E0759]: `u` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
 LL | fn error(u: &(), v: &()) {
    |             --- this data with an anonymous lifetime `'_`...
 LL |     static_id(&u);
-   |     ^^^^^^^^^ -- ...is captured here...
+   |     ^^^^^^^^^ -- ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/regions-static-bound.rs:10:5
@@ -32,7 +32,7 @@ LL | fn error(u: &(), v: &()) {
    |                     --- this data with an anonymous lifetime `'_`...
 LL |     static_id(&u);
 LL |     static_id_indirect(&v);
-   |     ^^^^^^^^^^^^^^^^^^ -- ...is captured here...
+   |     ^^^^^^^^^^^^^^^^^^ -- ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/regions-static-bound.rs:11:5
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
index 2961d8d7eac..63d291ed7cd 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
@@ -22,7 +22,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
 LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
    |                        -------------------------------------- this data with lifetime `'a`...
 LL |         val.use_self()
-   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |             ^^^^^^^^ ...is used and required to live as long as `'static` here
    |
 note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
index 6d9f0811b27..55a1bbf18ab 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
@@ -4,7 +4,7 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifeti
 LL |     fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
    |                           ---------------------- this data with lifetime `'a`...
 LL |         val.use_self::<T>()
-   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |             ^^^^^^^^ ...is used and required to live as long as `'static` here
    |
 note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32
@@ -24,7 +24,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
    |                        ------------------- this data with lifetime `'a`...
 LL |         val.use_self()
-   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl`
+   |             ^^^^^^^^ ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl`
    |
 note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
@@ -44,7 +44,7 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifeti
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
    |                        ------------------- this data with lifetime `'a`...
 LL |         val.use_self()
-   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |             ^^^^^^^^ ...is used and required to live as long as `'static` here
    |
 note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26
@@ -69,7 +69,7 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifeti
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
    |                        ------------------- this data with lifetime `'a`...
 LL |         MyTrait::use_self(val)
-   |                           ^^^ ...is captured here...
+   |                           ^^^ ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
@@ -95,7 +95,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
    |                        ------------------- this data with lifetime `'a`...
 LL |         val.use_self()
-   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |             ^^^^^^^^ ...is used and required to live as long as `'static` here
    |
 note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
@@ -115,7 +115,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
 LL |     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
    |                        ----------------------------- this data with lifetime `'a`...
 LL |         val.use_self()
-   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |             ^^^^^^^^ ...is used and required to live as long as `'static` here
    |
 note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
index 1ca22ebeef4..a5b50634c71 100644
--- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
+++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
@@ -7,7 +7,7 @@ LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is captured here...
+   |                        ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/trait-object-nested-in-impl-trait.rs:27:23
@@ -32,7 +32,7 @@ LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is captured here...
+   |                        ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/trait-object-nested-in-impl-trait.rs:38:23
@@ -53,7 +53,7 @@ LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is captured here...
+   |                        ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/trait-object-nested-in-impl-trait.rs:49:30
@@ -74,7 +74,7 @@ LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
 LL |             remaining: self.0.iter(),
    |                        ------ ^^^^
    |                        |
-   |                        ...is captured here...
+   |                        ...is used here...
    |
 note: ...and is required to live as long as `'static` here
   --> $DIR/trait-object-nested-in-impl-trait.rs:60:30
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..d4bb9350b0b 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
@@ -36,12 +36,88 @@ LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
 LL |     let y = x as &dyn Bar<'_, '_>;
    |             -             ^^
    |             |
-   |             ...is captured here...
+   |             ...is used here...
 LL |
 LL |     y.get_b() // ERROR
-   |     --------- ...and is required to live as long as `'static` here
+   |     - ...is used here...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/type-checking-test-4.rs:29:5
+   |
+LL |     y.get_b() // ERROR
+   |     ^^^^^^^^^
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/type-checking-test-4.rs:26:48
+   |
+LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                                                ^^^^^^^ `'static` requirement introduced here
+...
+LL |     y.get_b() // ERROR
+   |     --------- because of this returned expression
+
+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 used and required to live as long as `'static` here
+   |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/type-checking-test-4.rs:32:48
+   |
+LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                                                ^^^^^^^ `'static` requirement introduced here
+LL |     <_ as Bar>::get_b(x) // ERROR
+   |     -------------------- because of this returned expression
+
+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 used and required to live as long as `'static` here
+   |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/type-checking-test-4.rs:37:48
+   |
+LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                                                ^^^^^^^ `'static` requirement introduced here
+LL |     <_ as Bar<'_, '_>>::get_b(x) // ERROR
+   |     ---------------------------- because of this returned expression
+
+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 used here...
+LL |
+LL |     y.get_b(); // ERROR
+   |     - ...is used here...
+LL |     let z = y;
+LL |     z.get_b() // ERROR
+   |     - ...is used here...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/type-checking-test-4.rs:47:5
+   |
+LL |     z.get_b() // ERROR
+   |     ^^^^^^^^^
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/type-checking-test-4.rs:42:48
+   |
+LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
+   |                                                ^^^^^^^ `'static` requirement introduced here
+...
+LL |     z.get_b() // ERROR
+   |     --------- because of this returned expression
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0308, E0759.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index de3a6bbae17..f4285a0f98e 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -5,8 +5,18 @@ LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
    |                ---- this data with an anonymous lifetime `'_`...
 LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
 LL |     Box::new(items.iter())
-   |     ---------------^^^^--- ...is captured and required to live as long as `'static` here
+   |              ----- ^^^^
+   |              |
+   |              ...is used and required to live as long as `'static` here
    |
+note: `'static` lifetime requirement introduced by the return type
+  --> $DIR/dyn-trait-underscore.rs:6:29
+   |
+LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+   |                             ^^^^^^^^^^^^^^^^^^^^^ `'static` requirement introduced here
+LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+LL |     Box::new(items.iter())
+   |     ---------------------- because of this returned expression
 help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {