about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-06-18 15:20:43 -0700
committerGitHub <noreply@github.com>2020-06-18 15:20:43 -0700
commit40fd2bdcfec7a30a2cce0d4a2cc08d09e64cabeb (patch)
tree2e3e2f8e3065fbaa7761329779288ea5cbebe6c6 /src
parent9262fc2a68133330a8f78c73afa54b3ff09724b5 (diff)
parentbfe1434d3bb849d3eb993c42fb57aa0819f9be65 (diff)
downloadrust-40fd2bdcfec7a30a2cce0d4a2cc08d09e64cabeb.tar.gz
rust-40fd2bdcfec7a30a2cce0d4a2cc08d09e64cabeb.zip
Rollup merge of #72804 - estebank:opaque-missing-lts-in-fn-2, r=nikomatsakis
Further tweak lifetime errors involving `dyn Trait` and `impl Trait` in return position

* Suggest substituting `'static` lifetime in impl/dyn `Trait + 'static` instead of `Trait + 'static + '_`
* When `'static` is explicit, also suggest constraining argument with it
* Reduce verbosity of suggestion message and mention lifetime in label
* Tweak output for overlapping required/captured spans
* Give these errors an error code

Follow up to #72543.

r? @nikomatsakis
Diffstat (limited to 'src')
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0759.md67
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs3
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs190
-rw-r--r--src/librustc_middle/ty/context.rs13
-rw-r--r--src/librustc_middle/ty/diagnostics.rs13
-rw-r--r--src/test/ui/async-await/issues/issue-62097.stderr7
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr38
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs21
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr174
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr31
-rw-r--r--src/test/ui/issues/issue-16922.stderr12
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr11
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr19
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.rs5
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.stderr63
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.stderr30
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.stderr30
-rw-r--r--src/test/ui/regions/regions-proc-bound-capture.nll.stderr11
-rw-r--r--src/test/ui/regions/regions-proc-bound-capture.rs4
-rw-r--r--src/test/ui/regions/regions-proc-bound-capture.stderr23
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr7
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr17
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr17
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr9
25 files changed, 611 insertions, 205 deletions
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 3fb5e04efc9..99ef226f94a 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -439,6 +439,7 @@ E0752: include_str!("./error_codes/E0752.md"),
 E0753: include_str!("./error_codes/E0753.md"),
 E0754: include_str!("./error_codes/E0754.md"),
 E0758: include_str!("./error_codes/E0758.md"),
+E0759: include_str!("./error_codes/E0759.md"),
 E0760: include_str!("./error_codes/E0760.md"),
 E0761: include_str!("./error_codes/E0761.md"),
 E0762: include_str!("./error_codes/E0762.md"),
diff --git a/src/librustc_error_codes/error_codes/E0759.md b/src/librustc_error_codes/error_codes/E0759.md
new file mode 100644
index 00000000000..a74759bdf63
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0759.md
@@ -0,0 +1,67 @@
+A `'static` requirement in a return type involving a trait is not fulfilled.
+
+Erroneous code examples:
+
+```compile_fail,E0759
+use std::fmt::Debug;
+
+fn foo(x: &i32) -> impl Debug {
+    x
+}
+```
+
+```compile_fail,E0759
+# use std::fmt::Debug;
+fn bar(x: &i32) -> Box<dyn Debug> {
+    Box::new(x)
+}
+```
+
+These examples have the same semantics as the following:
+
+```compile_fail,E0759
+# use std::fmt::Debug;
+fn foo(x: &i32) -> impl Debug + 'static {
+    x
+}
+```
+
+```compile_fail,E0759
+# use std::fmt::Debug;
+fn bar(x: &i32) -> Box<dyn Debug + 'static> {
+    Box::new(x)
+}
+```
+
+Both [`dyn Trait`] and [`impl Trait`] in return types have a an implicit
+`'static` requirement, meaning that the value implementing them that is being
+returned has to be either a `'static` borrow or an owned value.
+
+In order to change the requirement from `'static` to be a lifetime derived from
+its arguments, you can add an explicit bound, either to an anonymous lifetime
+`'_` or some appropriate named lifetime.
+
+```
+# use std::fmt::Debug;
+fn foo(x: &i32) -> impl Debug + '_ {
+    x
+}
+fn bar(x: &i32) -> Box<dyn Debug + '_> {
+    Box::new(x)
+}
+```
+
+These are equivalent to the following explicit lifetime annotations:
+
+```
+# use std::fmt::Debug;
+fn foo<'a>(x: &'a i32) -> impl Debug + 'a {
+    x
+}
+fn bar<'a>(x: &'a i32) -> Box<dyn Debug + 'a> {
+    Box::new(x)
+}
+```
+
+[`dyn Trait`]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
+[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 12f7a9c0ca5..9cfa11dd7c8 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -2035,8 +2035,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             self.tcx.sess,
             var_origin.span(),
             E0495,
-            "cannot infer an appropriate lifetime{} \
-             due to conflicting requirements",
+            "cannot infer an appropriate lifetime{} due to conflicting requirements",
             var_description
         )
     }
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index f4c86ddae60..82feebc8029 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -1,14 +1,15 @@
 //! Error Reporting for static impl Traits.
 
-use crate::infer::error_reporting::msg_span_from_free_region;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use rustc_errors::{Applicability, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, ErrorReported};
+use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
 use rustc_middle::ty::RegionKind;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
     pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
+        debug!("try_report_static_impl_trait(error={:?})", self.error);
         if let Some(ref error) = self.error {
             if let RegionResolutionError::SubSupConflict(
                 _,
@@ -17,18 +18,36 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 sub_r,
                 sup_origin,
                 sup_r,
-            ) = error.clone()
+            ) = error
             {
+                debug!(
+                    "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
+                    var_origin, sub_origin, sub_r, sup_origin, sup_r
+                );
                 let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
-                let (fn_return_span, is_dyn) =
-                    self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
-                if sub_r == &RegionKind::ReStatic {
+                debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
+                let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
+                debug!("try_report_static_impl_trait: fn_return={:?}", fn_return);
+                if **sub_r == RegionKind::ReStatic {
                     let sp = var_origin.span();
                     let return_sp = sub_origin.span();
-                    let mut err =
-                        self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime");
                     let param_info = self.find_param_with_region(sup_r, sub_r)?;
-                    err.span_label(param_info.param_ty_span, "data with this lifetime...");
+                    let (lifetime_name, lifetime) = if sup_r.has_name() {
+                        (sup_r.to_string(), format!("lifetime `{}`", sup_r))
+                    } else {
+                        ("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
+                    };
+                    let mut err = struct_span_err!(
+                        self.tcx().sess,
+                        sp,
+                        E0759,
+                        "cannot infer an appropriate lifetime"
+                    );
+                    err.span_label(
+                        param_info.param_ty_span,
+                        &format!("this data with {}...", lifetime),
+                    );
+                    debug!("try_report_static_impl_trait: param_info={:?}", param_info);
 
                     // We try to make the output have fewer overlapping spans if possible.
                     if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
@@ -38,41 +57,146 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
                         // Customize the spans and labels depending on their relative order so
                         // that split sentences flow correctly.
-                        if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() {
-                            err.span_label(sup_origin.span(), "...is captured here...");
-                            err.span_label(return_sp, "...and required to be `'static` by this");
+                        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) }
+                            //    |           ----                      ---------^-
+                            //
+                            // and instead show:
+                            //
+                            // 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`",
+                            );
                         } else {
-                            err.span_label(return_sp, "...is required to be `'static` by this...");
-                            err.span_label(sup_origin.span(), "...and is captured here");
+                            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",
+                                );
+                            } else {
+                                err.span_label(
+                                    return_sp,
+                                    "...and is required to live as long as `'static` here",
+                                );
+                            }
                         }
                     } else {
                         err.span_label(
                             return_sp,
-                            "...is captured and required to be `'static` here",
+                            "...is captured and required to live as long as `'static` here",
                         );
                     }
 
-                    let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r);
-
-                    let lifetime_name =
-                        if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
                     // only apply this suggestion onto functions with
                     // explicit non-desugar'able return.
-                    if fn_return_span.desugaring_kind().is_none() {
-                        let msg = format!(
-                            "to permit non-static references in {} `{} Trait` value, you can add \
-                             an explicit bound for {}",
-                            if is_dyn { "a" } else { "an" },
-                            if is_dyn { "dyn" } else { "impl" },
-                            lifetime,
-                        );
+                    if fn_return.span.desugaring_kind().is_none() {
                         // FIXME: account for the need of parens in `&(dyn Trait + '_)`
-                        err.span_suggestion_verbose(
-                            fn_return_span.shrink_to_hi(),
-                            &msg,
-                            format!(" + {}", lifetime_name),
-                            Applicability::MaybeIncorrect,
-                        );
+
+                        let consider = "consider changing the";
+                        let declare = "to declare that the";
+                        let arg = match param_info.param.pat.simple_ident() {
+                            Some(simple_ident) => format!("argument `{}`", simple_ident),
+                            None => "the argument".to_string(),
+                        };
+                        let explicit =
+                            format!("you can add an explicit `{}` lifetime bound", lifetime_name);
+                        let explicit_static =
+                            format!("explicit `'static` bound to the lifetime of {}", arg);
+                        let captures = format!("captures data from {}", arg);
+                        let add_static_bound =
+                            "alternatively, add an explicit `'static` bound to this reference";
+                        let plus_lt = format!(" + {}", lifetime_name);
+                        match fn_return.kind {
+                            TyKind::OpaqueDef(item_id, _) => {
+                                let item = self.tcx().hir().item(item_id.id);
+                                let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
+                                    opaque
+                                } else {
+                                    err.emit();
+                                    return Some(ErrorReported);
+                                };
+
+                                if let Some(span) = opaque
+                                    .bounds
+                                    .iter()
+                                    .filter_map(|arg| match arg {
+                                        GenericBound::Outlives(Lifetime {
+                                            name: LifetimeName::Static,
+                                            span,
+                                            ..
+                                        }) => Some(*span),
+                                        _ => None,
+                                    })
+                                    .next()
+                                {
+                                    err.span_suggestion_verbose(
+                                        span,
+                                        &format!("{} `impl Trait`'s {}", consider, explicit_static),
+                                        lifetime_name,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                    err.span_suggestion_verbose(
+                                        param_info.param_ty_span,
+                                        add_static_bound,
+                                        param_info.param_ty.to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                } else {
+                                    err.span_suggestion_verbose(
+                                        fn_return.span.shrink_to_hi(),
+                                        &format!(
+                                            "{declare} `impl Trait` {captures}, {explicit}",
+                                            declare = declare,
+                                            captures = captures,
+                                            explicit = explicit,
+                                        ),
+                                        plus_lt,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                };
+                            }
+                            TyKind::TraitObject(_, lt) => match lt.name {
+                                LifetimeName::ImplicitObjectLifetimeDefault => {
+                                    err.span_suggestion_verbose(
+                                        fn_return.span.shrink_to_hi(),
+                                        &format!(
+                                            "{declare} trait object {captures}, {explicit}",
+                                            declare = declare,
+                                            captures = captures,
+                                            explicit = explicit,
+                                        ),
+                                        plus_lt,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                                _ => {
+                                    err.span_suggestion_verbose(
+                                        lt.span,
+                                        &format!("{} trait object's {}", consider, explicit_static),
+                                        lifetime_name,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                    err.span_suggestion_verbose(
+                                        param_info.param_ty_span,
+                                        add_static_bound,
+                                        param_info.param_ty.to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                            },
+                            _ => {}
+                        }
                     }
                     err.emit();
                     return Some(ErrorReported);
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index a553630e427..62d6de2d71e 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1405,7 +1405,10 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> {
+    pub fn return_type_impl_or_dyn_trait(
+        &self,
+        scope_def_id: DefId,
+    ) -> Option<&'tcx hir::Ty<'tcx>> {
         let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local());
         let hir_output = match self.hir().get(hir_id) {
             Node::Item(hir::Item {
@@ -1451,15 +1454,17 @@ impl<'tcx> TyCtxt<'tcx> {
                 let output = self.erase_late_bound_regions(&sig.output());
                 if output.is_impl_trait() {
                     let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
-                    Some((fn_decl.output.span(), false))
+                    if let hir::FnRetTy::Return(ty) = fn_decl.output {
+                        return Some(ty);
+                    }
                 } else {
                     let mut v = TraitObjectVisitor(vec![]);
                     rustc_hir::intravisit::walk_ty(&mut v, hir_output);
                     if v.0.len() == 1 {
-                        return Some((v.0[0], true));
+                        return Some(v.0[0]);
                     }
-                    None
                 }
+                None
             }
             _ => None,
         }
diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs
index 2e9aa724ac5..a2812e117ed 100644
--- a/src/librustc_middle/ty/diagnostics.rs
+++ b/src/librustc_middle/ty/diagnostics.rs
@@ -236,21 +236,24 @@ pub fn suggest_constraining_type_param(
     }
 }
 
-pub struct TraitObjectVisitor(pub Vec<rustc_span::Span>);
-impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor {
+pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>);
+impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'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_ty(&mut self, ty: &hir::Ty<'_>) {
+    fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
         if let hir::TyKind::TraitObject(
             _,
-            hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
+            hir::Lifetime {
+                name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
+                ..
+            },
         ) = ty.kind
         {
-            self.0.push(ty.span);
+            self.0.push(ty);
         }
     }
 }
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index af8fc2cd2ab..0f58b158904 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -1,13 +1,14 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/issue-62097.rs:12:31
    |
 LL |     pub async fn run_dummy_fn(&self) {
    |                               ^^^^^
    |                               |
-   |                               data with this lifetime...
+   |                               this data with an anonymous lifetime `'_`...
    |                               ...is captured here...
 LL |         foo(|| self.bar()).await;
-   |         --- ...and required to be `'static` by this
+   |         --- ...and is required to live as long as `'static` here
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 1806d2607a3..ca9ca8a9deb 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -26,7 +26,34 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                ^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+   |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+   |               -                              ^ returning this value requires that `'1` must outlive `'static`
+   |               |
+   |               let's call the lifetime of this reference `'1`
+   |
+   = help: consider replacing `'1` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+   |              -- lifetime `'a` defined here            ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+   = help: consider replacing `'a` with `'static`
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/must_outlive_least_region_or_bound.rs:15:41
+   |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+   |               ----                      ^ lifetime `'a` required
+   |               |
+   |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error: lifetime may not live long enough
+  --> $DIR/must_outlive_least_region_or_bound.rs:33:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
@@ -35,7 +62,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:38:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                          --  -- lifetime `'b` defined here  ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
@@ -45,13 +72,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    = help: consider adding the following bound: `'b: 'a`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:43:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                                   ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
-error: aborting due to 5 previous errors
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0310`.
+Some errors have detailed explanations: E0310, E0621.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
index 00f3490991b..837244b0227 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -6,6 +6,27 @@ fn elided(x: &i32) -> impl Copy { x }
 fn explicit<'a>(x: &'a i32) -> impl Copy { x }
 //~^ ERROR cannot infer an appropriate lifetime
 
+fn elided2(x: &i32) -> impl Copy + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+//~^ ERROR explicit lifetime required in the type of `x`
+
+fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
 trait LifetimeTrait<'a> {}
 impl<'a> LifetimeTrait<'a> for &'a i32 {}
 
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 d7dae6a08a7..e1fa4f02b6f 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
@@ -1,47 +1,113 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----     ---------   ^ ...and is captured here
-   |              |        |
-   |              |        ...is required to be `'static` by this...
-   |              data with this lifetime...
+   |              ----                 ^ ...is captured here...
+   |              |
+   |              this data with an anonymous lifetime `'_`...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:23
+   |
+LL | fn elided(x: &i32) -> impl Copy { x }
+   |                       ^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ^^^^
 
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |                    -------     ---------   ^ ...and is captured here
-   |                    |           |
-   |                    |           ...is required to be `'static` by this...
-   |                    data with this lifetime...
+   |                    -------                 ^ ...is captured here...
+   |                    |
+   |                    this data with lifetime `'a`...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+   |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
+   |                                ^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                          ^^^^
 
-error: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+   |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+   |               ----                           ^ ...is captured here...
+   |               |
+   |               this data with an anonymous lifetime `'_`...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:24
+   |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+   |                        ^^^^^^^^^^^^^^^^^^^
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
+   |                                    ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
+   |               ^^^^^^^^^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+   |                     -------                           ^ ...is captured here...
+   |                     |
+   |                     this data with lifetime `'a`...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:33
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+   |                                 ^^^^^^^^^^^^^^^^^^^
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
+   |                                             ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
+   |                     ^^^^^^^^^^^^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/must_outlive_least_region_or_bound.rs:15:24
+   |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+   |               ----     ^^^^^^^^^^^^^^ lifetime `'a` required
+   |               |
+   |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:33:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                      -------     --------------------------------   ^ ...and is captured here
-   |                      |           |
-   |                      |           ...is required to be `'static` by this...
-   |                      data with this lifetime...
+   |                      ------- this data with lifetime `'a`...        ^ ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:33:34
+   |
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
-   |                                                                   ^^^^
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
+   |                                                           ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
+   |                      ^^^^^^^^^^^^
 
 error[E0623]: lifetime mismatch
-  --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:38:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                                                 -------     ^^^^^^^^^^^^^^^^
@@ -50,14 +116,72 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                 this parameter and the return type are declared with different lifetimes...
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:43:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                 --                ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |                                 |
    |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
 
-error: aborting due to 5 previous errors
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+   |
+LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+   |               ----                               ^ ...is captured here, requiring it to live as long as `'static`
+   |               |
+   |               this data with an anonymous lifetime `'_`...
+   |
+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) }
+   |                                      ^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:21: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`
+   |                     |
+   |                     this data with lifetime `'a`...
+   |
+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) }
+   |                                               ^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:24:60
+   |
+LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |               ----                                         ^ ...is captured here, requiring it to live as long as `'static`
+   |               |
+   |               this data with an anonymous lifetime `'_`...
+   |
+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) }
+   |                                        ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |               ^^^^^^^^^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:27: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`
+   |
+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) }
+   |                                                 ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |                     ^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
-Some errors have detailed explanations: E0310, E0623.
+Some errors have detailed explanations: E0310, E0621, E0623, E0759.
 For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index 1c3a5979ee5..df0db6e4fc6 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -1,36 +1,43 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/static-return-lifetime-infered.rs:7:16
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         -----     ----------------------- ...is required to be `'static` by this...
-   |                         |
-   |                         data with this lifetime...
+   |                         ----- this data with an anonymous lifetime `'_`...
 LL |         self.x.iter().map(|a| a.0)
    |         ------ ^^^^
    |         |
-   |         ...and is captured here
+   |         ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5
+note: ...and is required to live as long as `'static` here
+  --> $DIR/static-return-lifetime-infered.rs:6:35
+   |
+LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ^^^^
 
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/static-return-lifetime-infered.rs:11:16
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                        --------     ----------------------- ...is required to be `'static` by this...
-   |                        |
-   |                        data with this lifetime...
+   |                        -------- this data with lifetime `'a`...
 LL |         self.x.iter().map(|a| a.0)
    |         ------ ^^^^
    |         |
-   |         ...and is captured here
+   |         ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20
+note: ...and is required to live as long as `'static` here
+  --> $DIR/static-return-lifetime-infered.rs:10:37
+   |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ^^^^
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 02d33aae023..919594fc9af 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -1,18 +1,16 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/issue-16922.rs:4:14
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
-   |                       -- data with this lifetime...
+   |                       -- this data with an anonymous lifetime `'_`...
 LL |     Box::new(value) as Box<dyn Any>
-   |     ---------^^^^^-
-   |     |        |
-   |     |        ...and is captured here
-   |     ...is required to be `'static` by this...
+   |              ^^^^^ ...is captured here, requiring it to live as long as `'static`
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any + '_> {
    |                                          ^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
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 70a9bf22b8d..1b1e0d96107 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
@@ -1,13 +1,13 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
-   |             --------------- data with this lifetime...
+   |             --------------- this data with an anonymous lifetime `'_`...
 ...
 LL |     ss.r
-   |     ^^^^ ...is captured and required to be `'static` here
+   |     ^^^^ ...is captured and required to live as long as `'static` here
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
+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 + '_> {
    |                                                   ^^^^
@@ -23,4 +23,5 @@ LL |     ss.r = b;
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0621`.
+Some errors have detailed explanations: E0621, E0759.
+For more information about an error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
index bf02ba8eb91..7e8f78067e0 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
@@ -1,21 +1,21 @@
-error[E0621]: explicit lifetime required in the type of `v`
+error: lifetime may not live long enough
   --> $DIR/region-object-lifetime-in-coercion.rs:8:12
    |
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         - let's call the lifetime of this reference `'1`
 LL |     let x: Box<dyn Foo + 'static> = Box::new(v);
-   |            ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+   |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
 
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+error: lifetime may not live long enough
+  --> $DIR/region-object-lifetime-in-coercion.rs:13:5
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         - let's call the lifetime of this reference `'1`
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^ lifetime `'static` required
+   |     ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/region-object-lifetime-in-coercion.rs:20:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:19:5
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
    |         - let's call the lifetime of this reference `'1`
@@ -24,7 +24,7 @@ LL |     Box::new(v)
    |     ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:5
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      -- -- lifetime `'b` defined here
@@ -37,4 +37,3 @@ LL |     Box::new(v)
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
index d56eaf77b66..5d199149c39 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -5,13 +5,12 @@ trait Foo {}
 impl<'a> Foo for &'a [u8] {}
 
 fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-    let x: Box<dyn Foo + 'static> = Box::new(v);
-    //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+    let x: Box<dyn Foo + 'static> = Box::new(v); //~ ERROR cannot infer an appropriate lifetime
     x
 }
 
 fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-    Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621]
+    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn c(v: &[u8]) -> Box<dyn Foo> {
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 1462af44cb1..7f5a3a47976 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -1,61 +1,76 @@
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:8:37
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:8:46
    |
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         ----- this data with an anonymous lifetime `'_`...
 LL |     let x: Box<dyn Foo + 'static> = Box::new(v);
-   |                                     ^^^^^^^^^^^ lifetime `'static` required
+   |                                              ^ ...is captured here, requiring it to live as long as `'static`
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+   |
+LL | fn a(v: &[u8]) -> Box<dyn Foo + '_> {
+   |                                 ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn a(v: &'static [u8]) -> Box<dyn Foo + 'static> {
+   |         ^^^^^^^^^^^^^
 
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:13:14
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         ----- this data with an anonymous lifetime `'_`...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^ lifetime `'static` required
+   |              ^ ...is captured here, requiring it to live as long as `'static`
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+   |
+LL | fn b(v: &[u8]) -> Box<dyn Foo + '_> {
+   |                                 ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn b(v: &'static [u8]) -> Box<dyn Foo + 'static> {
+   |         ^^^^^^^^^^^^^
 
-error: cannot infer an appropriate lifetime
-  --> $DIR/region-object-lifetime-in-coercion.rs:20:14
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:19:14
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
-   |         ----- data with this lifetime...
+   |         ----- this data with an anonymous lifetime `'_`...
 ...
 LL |     Box::new(v)
-   |     ---------^-
-   |     |        |
-   |     |        ...and is captured here
-   |     ...is required to be `'static` by this...
+   |              ^ ...is captured here, requiring it to live as long as `'static`
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1
+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 + '_> {
    |                               ^^^^
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:14
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:14
    |
 LL |     Box::new(v)
    |              ^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6...
-  --> $DIR/region-object-lifetime-in-coercion.rs:23:6
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:6...
+  --> $DIR/region-object-lifetime-in-coercion.rs:22:6
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      ^^
 note: ...so that the expression is assignable
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:14
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:14
    |
 LL |     Box::new(v)
    |              ^
    = note: expected `&[u8]`
               found `&'a [u8]`
-note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9...
-  --> $DIR/region-object-lifetime-in-coercion.rs:23:9
+note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 22:9...
+  --> $DIR/region-object-lifetime-in-coercion.rs:22:9
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |         ^^
 note: ...so that the expression is assignable
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:5
    |
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
@@ -64,5 +79,5 @@ LL |     Box::new(v)
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0495, E0621.
+Some errors have detailed explanations: E0495, E0759.
 For more information about an error, try `rustc --explain E0495`.
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 147f7f35418..114e4052aae 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
@@ -1,28 +1,20 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/regions-close-object-into-object-2.rs:10:11
    |
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
+   |                         ------------------ this data with lifetime `'a`...
 LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
-  --> $DIR/regions-close-object-into-object-2.rs:9:6
+   |           ^^^ ...is captured here, requiring it to live as long as `'static`
    |
-LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
-   |      ^^
-note: ...so that the type `(dyn A<T> + 'a)` is not borrowed for too long
-  --> $DIR/regions-close-object-into-object-2.rs:10:11
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
-LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/regions-close-object-into-object-2.rs:10:5
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'a> {
+   |                                                            ^^
+help: alternatively, add an explicit `'static` bound to this reference
    |
-LL |     box B(&*v) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `std::boxed::Box<(dyn X + 'static)>`
-              found `std::boxed::Box<dyn X>`
+LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A<T> + 'static)>) -> Box<dyn X + 'static> {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
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 6e7d6152cd0..850d8194079 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
@@ -1,28 +1,20 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/regions-close-object-into-object-4.rs:10:11
    |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |                   ---------------- this data with lifetime `'a`...
 LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
-  --> $DIR/regions-close-object-into-object-4.rs:9:6
+   |           ^^^ ...is captured here, requiring it to live as long as `'static`
    |
-LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
-   |      ^^
-note: ...so that the type `(dyn A<U> + 'a)` is not borrowed for too long
-  --> $DIR/regions-close-object-into-object-4.rs:10:11
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
-LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/regions-close-object-into-object-4.rs:10:5
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'a> {
+   |                                                    ^^
+help: alternatively, add an explicit `'static` bound to this reference
    |
-LL |     box B(&*v) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `std::boxed::Box<(dyn X + 'static)>`
-              found `std::boxed::Box<dyn X>`
+LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A<U> + 'static)>) -> Box<dyn X + 'static> {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/regions/regions-proc-bound-capture.nll.stderr b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
new file mode 100644
index 00000000000..75890b85815
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-proc-bound-capture.rs:9:5
+   |
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+   |                   - let's call the lifetime of this reference `'1`
+LL |     // This is illegal, because the region bound on `proc` is 'static.
+LL |     Box::new(move || { *x })
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs
index 0c903b73849..8617c0e9da8 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.rs
+++ b/src/test/ui/regions/regions-proc-bound-capture.rs
@@ -4,9 +4,9 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box<dyn FnMut()->(isize) + 'a> {
     Box::new(move|| { *x })
 }
 
-fn static_proc(x: &isize) -> Box<dyn FnMut()->(isize) + 'static> {
+fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
     // This is illegal, because the region bound on `proc` is 'static.
-    Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
+    Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() { }
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index c53af34456e..67eee3bb6e2 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -1,12 +1,21 @@
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/regions-proc-bound-capture.rs:9:5
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/regions-proc-bound-capture.rs:9:14
    |
-LL | fn static_proc(x: &isize) -> Box<dyn FnMut()->(isize) + 'static> {
-   |                   ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
+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 })
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+LL |     Box::new(move || { *x })
+   |              ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static`
+   |
+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) + '_> {
+   |                                                           ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn static_proc(x: &'static isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+   |                   ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0621`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 1aeabce5e8a..88bd990b1e8 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -1,11 +1,12 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                ^^^^  ----------     ---------- ...and required to be `'static` by this
+   |                ^^^^  ----------     ---------- ...and is required to live as long as `'static` here
    |                |     |
-   |                |     data with this lifetime...
+   |                |     this data with an anonymous lifetime `'_`...
    |                ...is captured here...
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 04c475be787..2e10ab3d3f9 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -1,16 +1,21 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                ----------     ----------   ^^^^ ...and is captured here
-   |                |              |
-   |                |              ...is required to be `'static` by this...
-   |                data with this lifetime...
+   |                ----------                  ^^^^ ...is captured here...
+   |                |
+   |                this data with an anonymous lifetime `'_`...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5
+note: ...and is required to live as long as `'static` here
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                               ^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                                          ^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index 5cf170d566c..9ab06032853 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -6,20 +6,23 @@ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/missing-lifetimes-in-signature.rs:19:5
    |
 LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                            ------     ------------- ...is required to be `'static` by this...
-   |                            |
-   |                            data with this lifetime...
+   |                            ------ this data with an anonymous lifetime `'_`...
 ...
 LL | /     move || {
 LL | |         *dest = g.get();
 LL | |     }
-   | |_____^ ...and is captured here
+   | |_____^ ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1
+note: ...and is required to live as long as `'static` here
+  --> $DIR/missing-lifetimes-in-signature.rs:15:37
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+   |                                     ^^^^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound
    |
 LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |                                                   ^^^^
@@ -122,5 +125,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
 
 error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0261, E0309, E0621.
+Some errors have detailed explanations: E0261, E0309, E0621, E0759.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index 3577dd59289..dda5de431d3 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -1,16 +1,17 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/dyn-trait-underscore.rs:8:20
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
-   |                ---- data with this lifetime...
+   |                ---- this data with an anonymous lifetime `'_`...
 LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
 LL |     Box::new(items.iter())
-   |     ---------------^^^^--- ...is captured and required to be `'static` here
+   |     ---------------^^^^--- ...is captured and required to live as long as `'static` here
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1
+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> + '_> {
    |                                                   ^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.