From 0ced817ed373cdc83cd2cc9dea75f9dc76436a07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Fri, 26 Jun 2020 18:52:00 -0700
Subject: [PATCH 1/8] Detect when `'static` obligation might come from an
 `impl`

Address #71341.
---
 .../nice_region_error/static_impl_trait.rs    | 465 ++++++++++--------
 .../cache/project-fn-ret-contravariant.rs     |   2 +-
 ...ject-fn-ret-contravariant.transmute.stderr |  23 +-
 .../cache/project-fn-ret-invariant.rs         |   2 +-
 .../project-fn-ret-invariant.transmute.stderr |  28 +-
 .../dyn-trait.stderr                          |  25 +-
 .../constant-in-expr-inherent-1.stderr        |  25 +-
 .../ui/regions/regions-addr-of-self.stderr    |  28 +-
 ...mplicit-static-bound-without-suggestion.rs |  14 +
 ...cit-static-bound-without-suggestion.stderr |  18 +
 ...dyn-trait-with-implicit-static-bound.fixed |  37 ++
 ...on-dyn-trait-with-implicit-static-bound.rs |  37 ++
 ...yn-trait-with-implicit-static-bound.stderr |  29 ++
 13 files changed, 431 insertions(+), 302 deletions(-)
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr

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 b6e971feb0e5f..da776f269d510 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
@@ -2,227 +2,302 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use rustc_errors::{struct_span_err, Applicability, ErrorReported};
-use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
-use rustc_middle::ty::RegionKind;
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::{
+    GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef,
+    TyKind,
+};
+use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor};
 
 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(RegionResolutionError::SubSupConflict(
-            _,
-            var_origin,
-            ref sub_origin,
-            sub_r,
-            ref sup_origin,
-            sup_r,
-        )) = self.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)?;
-            debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
-            let fn_returns = self.tcx().return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
-            if fn_returns.is_empty() {
-                return None;
+        let tcx = self.tcx();
+        let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? {
+            RegionResolutionError::SubSupConflict(
+                _,
+                var_origin,
+                sub_origin,
+                sub_r,
+                sup_origin,
+                sup_r,
+            ) if **sub_r == RegionKind::ReStatic => {
+                (var_origin, sub_origin, sub_r, sup_origin, sup_r)
             }
-            debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
-            if *sub_r == RegionKind::ReStatic {
-                let sp = var_origin.span();
-                let return_sp = sub_origin.span();
-                let param_info = self.find_param_with_region(sup_r, sub_r)?;
-                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);
+            _ => return None,
+        };
+        debug!(
+            "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
+            var_origin, sub_origin, sub_r, sup_origin, sup_r
+        );
+        let anon_reg_sup = tcx.is_suitable_region(sup_r)?;
+        debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
+        let sp = var_origin.span();
+        let return_sp = sub_origin.span();
+        let param = self.find_param_with_region(sup_r, sub_r)?;
+        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!(tcx.sess, sp, E0759, "cannot infer an appropriate 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`
+        // 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) }
-                        //    |           ----                      ---------^-
-                        //
-                        // 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(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",
-                            );
-                        }
-                    }
+            // 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) }
+                //    |           ----                      ---------^-
+                //
+                // 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(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,
-                        "...is captured and required to live as long as `'static` here",
+                        "...and is required to live as long as `'static` here",
                     );
                 }
+            }
+        } else {
+            err.span_label(
+                return_sp,
+                "...is captured and required to live as long as `'static` here",
+            );
+        }
 
-                // FIXME: account for the need of parens in `&(dyn Trait + '_)`
-                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);
-                for fn_return in fn_returns {
-                    if fn_return.span.desugaring_kind().is_some() {
-                        // Skip `async` desugaring `impl Future`.
-                        continue;
-                    }
-                    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);
-                            };
+        self.find_impl_on_dyn_trait(&mut err, param.param_ty);
 
-                            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.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                err.span_suggestion_verbose(
-                                    param_info.param_ty_span,
-                                    add_static_bound,
-                                    param_info.param_ty.to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else if let Some(_) = opaque
-                                .bounds
-                                .iter()
-                                .filter_map(|arg| match arg {
-                                    GenericBound::Outlives(Lifetime { name, span, .. })
-                                        if name.ident().to_string() == lifetime_name =>
-                                    {
-                                        Some(*span)
-                                    }
-                                    _ => None,
-                                })
-                                .next()
+        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
+        debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
+        // FIXME: account for the need of parens in `&(dyn Trait + '_)`
+        let consider = "consider changing the";
+        let declare = "to declare that the";
+        let arg = match param.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);
+        for fn_return in fn_returns {
+            if fn_return.span.desugaring_kind().is_some() {
+                // Skip `async` desugaring `impl Future`.
+                continue;
+            }
+            match fn_return.kind {
+                TyKind::OpaqueDef(item_id, _) => {
+                    let item = 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.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.span_suggestion_verbose(
+                            param.param_ty_span,
+                            add_static_bound,
+                            param.param_ty.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else if let Some(_) = opaque
+                        .bounds
+                        .iter()
+                        .filter_map(|arg| match arg {
+                            GenericBound::Outlives(Lifetime { name, span, .. })
+                                if name.ident().to_string() == lifetime_name =>
                             {
-                            } 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.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
+                                Some(*span)
                             }
-                        }
-                        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.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
-                            name if name.ident().to_string() != lifetime_name => {
-                                // With this check we avoid suggesting redundant bounds. This
-                                // would happen if there are nested impl/dyn traits and only
-                                // one of them has the bound we'd suggest already there, like
-                                // in `impl Foo<X = dyn Bar> + '_`.
-                                err.span_suggestion_verbose(
-                                    lt.span,
-                                    &format!("{} trait object's {}", consider, explicit_static),
-                                    lifetime_name.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
+                            _ => None,
+                        })
+                        .next()
+                    {
+                    } 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.clone(),
+                            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.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    name if name.ident().to_string() != lifetime_name => {
+                        // With this check we avoid suggesting redundant bounds. This
+                        // would happen if there are nested impl/dyn traits and only
+                        // one of them has the bound we'd suggest already there, like
+                        // in `impl Foo<X = dyn Bar> + '_`.
+                        err.span_suggestion_verbose(
+                            lt.span,
+                            &format!("{} trait object's {}", consider, explicit_static),
+                            lifetime_name.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.span_suggestion_verbose(
+                            param.param_ty_span,
+                            add_static_bound,
+                            param.param_ty.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    _ => {}
+                },
+                _ => {}
+            }
+        }
+        err.emit();
+        Some(ErrorReported)
+    }
+
+    /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
+    /// `'static` obligation. Find `impl` blocks that are implemented
+    fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool {
+        let tcx = self.tcx();
+
+        // Find the trait object types in the argument.
+        let mut v = TraitObjectVisitor(vec![]);
+        v.visit_ty(ty);
+        debug!("TraitObjectVisitor {:?}", v.0);
+
+        // Find all the `impl`s in the local scope that can be called on the type parameter.
+        // FIXME: this doesn't find `impl dyn Trait { /**/ }`.
+        let impl_self_tys = tcx
+            .all_traits(LOCAL_CRATE)
+            .iter()
+            .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
+            .filter_map(|impl_node| {
+                let impl_did = tcx.hir().local_def_id(*impl_node);
+                if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
+                    tcx.hir().get_if_local(impl_did.to_def_id())
+                {
+                    Some(self_ty)
+                } else {
+                    None
+                }
+            });
+        let mut suggested = false;
+        for self_ty in impl_self_tys {
+            if let TyKind::TraitObject(
+                poly_trait_refs,
+                Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
+            ) = self_ty.kind
+            {
+                for p in poly_trait_refs {
+                    if let PolyTraitRef {
+                        trait_ref:
+                            TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. },
+                        ..
+                    } = p
+                    {
+                        for found_did in &v.0 {
+                            if did == found_did {
+                                // We've found an `impl Foo for dyn Bar {}`.
+                                // FIXME: we should change this so it also works for
+                                // `impl Foo for Box<dyn Bar> {}`.
                                 err.span_suggestion_verbose(
-                                    param_info.param_ty_span,
-                                    add_static_bound,
-                                    param_info.param_ty.to_string(),
+                                    self_ty.span.shrink_to_hi(),
+                                    "this `impl` introduces an implicit `'static` requirement, \
+                                     consider changing it",
+                                    " + '_".to_string(),
                                     Applicability::MaybeIncorrect,
                                 );
+                                suggested = true;
                             }
-                            _ => {}
-                        },
-                        _ => {}
+                        }
                     }
                 }
                 err.emit();
                 return Some(ErrorReported);
             }
         }
-        None
+        suggested
+    }
+}
+
+/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
+struct TraitObjectVisitor(Vec<DefId>);
+
+impl TypeVisitor<'_> for TraitObjectVisitor {
+    fn visit_ty(&mut self, t: Ty<'_>) -> bool {
+        match t.kind {
+            ty::Dynamic(preds, RegionKind::ReStatic) => {
+                if let Some(def_id) = preds.principal_def_id() {
+                    self.0.push(def_id);
+                }
+                false
+            }
+            _ => t.super_visit_with(self),
+        }
     }
 }
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
index 8c6073e2f7a49..1eeb01ccc846e 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
+++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
@@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
 
 #[cfg(transmute)] // one instantiations: BAD
 fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
-   bar(foo, x) //[transmute]~ ERROR E0495
+   bar(foo, x) //[transmute]~ ERROR E0759
 }
 
 #[cfg(krisskross)] // two instantiations, mixing and matching: BAD
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 5ea98dcd4a972..36812d3c0441e 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
@@ -1,26 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/project-fn-ret-contravariant.rs:38:8
    |
-LL |    bar(foo, x)
-   |        ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8...
-  --> $DIR/project-fn-ret-contravariant.rs:37:8
-   |
 LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
-   |        ^^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/project-fn-ret-contravariant.rs:38:13
-   |
-LL |    bar(foo, x)
-   |             ^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/project-fn-ret-contravariant.rs:38:4
-   |
+   |                  ------- this data with lifetime `'a`...
 LL |    bar(foo, x)
-   |    ^^^^^^^^^^^
+   |    ----^^^---- ...is captured and required to live as long as `'static` here
 
 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/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
index 0034d796826de..08d864f7836d2 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
@@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
     // Cannot instantiate `foo` with any lifetime other than `'a`,
     // since it is provided as input.
 
-    bar(foo, x) //[transmute]~ ERROR E0495
+    bar(foo, x) //[transmute]~ ERROR E0759
 }
 
 #[cfg(krisskross)] // two instantiations, mixing and matching: BAD
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 ef57f9e0bc480..9cec0780b3ca8 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
@@ -1,30 +1,12 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/project-fn-ret-invariant.rs:49:9
    |
-LL |     bar(foo, x)
-   |         ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8...
-  --> $DIR/project-fn-ret-invariant.rs:45:8
-   |
 LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
-   |        ^^
-note: ...so that the expression is assignable
-  --> $DIR/project-fn-ret-invariant.rs:49:14
-   |
-LL |     bar(foo, x)
-   |              ^
-   = note: expected `Type<'_>`
-              found `Type<'a>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/project-fn-ret-invariant.rs:49:5
-   |
+   |                   -------- this data with lifetime `'a`...
+...
 LL |     bar(foo, x)
-   |     ^^^^^^^^^^^
-   = note: expected `Type<'static>`
-              found `Type<'_>`
+   |     ----^^^---- ...is captured and required to live as long as `'static` here
 
 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/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
index 268008c211129..397cb3750c266 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -1,30 +1,17 @@
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/dyn-trait.rs:20:16
    |
-LL |     static_val(x);
-   |                ^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26...
-  --> $DIR/dyn-trait.rs:19:26
-   |
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
-   |                          ^^
-note: ...so that the expression is assignable
-  --> $DIR/dyn-trait.rs:20:16
-   |
+   |                                 ------------------- this data with lifetime `'a`...
 LL |     static_val(x);
-   |                ^
-   = note: expected `std::boxed::Box<dyn std::fmt::Debug>`
-              found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the types are compatible
+   |                ^ ...is captured here...
+   |
+note: ...and is required to live as long as `'static` here
   --> $DIR/dyn-trait.rs:20:5
    |
 LL |     static_val(x);
    |     ^^^^^^^^^^
-   = note: expected `StaticTrait`
-              found `StaticTrait`
 
 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/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 8421dc1d0c130..f823f69c76f67 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
@@ -1,28 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/constant-in-expr-inherent-1.rs:8:5
    |
-LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8...
-  --> $DIR/constant-in-expr-inherent-1.rs:7:8
-   |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
-   |        ^^
-note: ...so that the types are compatible
-  --> $DIR/constant-in-expr-inherent-1.rs:8:5
-   |
-LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^
-   = note: expected `Foo<'_>`
-              found `Foo<'a>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/constant-in-expr-inherent-1.rs:8:5
-   |
+   |               ------- this data with lifetime `'a`...
 LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
 
 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-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr
index a0b8b6b51e5a1..c15a933379c85 100644
--- a/src/test/ui/regions/regions-addr-of-self.stderr
+++ b/src/test/ui/regions/regions-addr-of-self.stderr
@@ -1,29 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/regions-addr-of-self.rs:7:37
    |
+LL |     pub fn chase_cat(&mut self) {
+   |                      --------- this data with an anonymous lifetime `'_`...
 LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
-  --> $DIR/regions-addr-of-self.rs:6:5
-   |
-LL | /     pub fn chase_cat(&mut self) {
-LL | |         let p: &'static mut usize = &mut self.cats_chased;
-LL | |         *p += 1;
-LL | |     }
-   | |_____^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/regions-addr-of-self.rs:7:37
-   |
-LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/regions-addr-of-self.rs:7:37
-   |
-LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
 
 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/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs
new file mode 100644
index 0000000000000..dd53ee06ff5ee
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs
@@ -0,0 +1,14 @@
+trait OtherTrait<'a> {}
+impl<'a> OtherTrait<'a> for &'a () {}
+
+trait ObjectTrait {}
+
+impl dyn ObjectTrait {
+    fn use_self(&self) -> &() { panic!() }
+}
+
+fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+    val.use_self() //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr
new file mode 100644
index 0000000000000..4618b540c70ee
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9
+   |
+LL |     val.use_self()
+   |         ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&(dyn ObjectTrait + 'static)`
+              found reference `&(dyn ObjectTrait + 'a)`
+note: the lifetime `'a` as defined on the function body at 10:11...
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11
+   |
+LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |           ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
new file mode 100644
index 0000000000000..dfe475d3c0694
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
@@ -0,0 +1,37 @@
+// run-rustfix
+#![allow(dead_code)]
+
+mod foo {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+
+    impl MyTrait for dyn ObjectTrait + '_ {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+mod bar {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+
+    impl MyTrait for dyn ObjectTrait + '_ {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
new file mode 100644
index 0000000000000..85e6c2993b9b1
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -0,0 +1,37 @@
+// run-rustfix
+#![allow(dead_code)]
+
+mod foo {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+
+    impl MyTrait for dyn ObjectTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+mod bar {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+
+    impl MyTrait for dyn ObjectTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+fn main() {}
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
new file mode 100644
index 0000000000000..6780459adbeac
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
@@ -0,0 +1,29 @@
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13
+   |
+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
+   |
+help: this `impl` introduces an implicit `'static` requirement, consider changing it
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {
+   |                                      ^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13
+   |
+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
+   |
+help: this `impl` introduces an implicit `'static` requirement, consider changing it
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {
+   |                                      ^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0759`.

From bc528ebc5158486252d8609d266c0a924244fd4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 28 Jun 2020 15:26:12 -0700
Subject: [PATCH 2/8] Increase accuracy of lifetime bound on trait object impl
 suggestion

---
 src/librustc_hir/hir.rs                       |  12 +-
 src/librustc_infer/infer/combine.rs           |  10 +-
 .../infer/error_reporting/mod.rs              |   2 +-
 .../nice_region_error/static_impl_trait.rs    | 184 +++++++++++++-----
 .../error_reporting/nice_region_error/util.rs |  14 +-
 src/librustc_infer/infer/mod.rs               |  18 +-
 src/librustc_infer/lib.rs                     |   1 +
 src/librustc_middle/traits/mod.rs             |   2 +
 .../traits/structural_impls.rs                |   1 +
 src/librustc_middle/ty/mod.rs                 |   8 +-
 .../traits/error_reporting/suggestions.rs     |   1 +
 src/librustc_typeck/check/method/confirm.rs   |  24 ++-
 ...mplicit-static-bound-without-suggestion.rs |  14 --
 ...cit-static-bound-without-suggestion.stderr |  18 --
 ...dyn-trait-with-implicit-static-bound.fixed |  36 ++++
 ...rait-with-implicit-static-bound.nll.stderr |  22 +++
 ...on-dyn-trait-with-implicit-static-bound.rs |  36 ++++
 ...yn-trait-with-implicit-static-bound.stderr |  32 ++-
 18 files changed, 321 insertions(+), 114 deletions(-)
 delete mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs
 delete mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr

diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index f56522406b0a7..6474dc318d329 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2198,7 +2198,17 @@ pub enum IsAsync {
     NotAsync,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(
+    Copy,
+    Clone,
+    PartialEq,
+    RustcEncodable,
+    RustcDecodable,
+    Debug,
+    HashStable_Generic,
+    Eq,
+    Hash
+)]
 pub enum Defaultness {
     Default { has_value: bool },
     Final,
diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs
index 3b564e03d9a94..c63464e5baec9 100644
--- a/src/librustc_infer/infer/combine.rs
+++ b/src/librustc_infer/infer/combine.rs
@@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations};
 
 use rustc_ast::ast;
 use rustc_hir::def_id::DefId;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{IntType, UintType};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::DUMMY_SP;
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
@@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         };
 
         debug!("generalize: for_universe = {:?}", for_universe);
+        debug!("generalize: trace = {:?}", self.trace);
 
         let mut generalize = Generalizer {
             infcx: self.infcx,
-            span: self.trace.cause.span,
+            cause: &self.trace.cause,
             for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
             for_universe,
             ambient_variance,
@@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
 
     /// The span, used when creating new type variables and things.
-    span: Span,
+    cause: &'cx ObligationCause<'tcx>,
 
     /// The vid of the type variable that is in the process of being
     /// instantiated; if we find this within the type we are folding,
@@ -639,7 +641,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
 
         // FIXME: This is non-ideal because we don't give a
         // very descriptive origin for this region variable.
-        Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
+        Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
     }
 
     fn consts(
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 633589db2704c..ff905faa95a9f 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -2010,7 +2010,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             infer::MiscVariable(_) => String::new(),
             infer::PatternRegion(_) => " for pattern".to_string(),
             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
-            infer::Autoref(_) => " for autoref".to_string(),
+            infer::Autoref(_, _) => " for autoref".to_string(),
             infer::Coercion(_) => " for automatic coercion".to_string(),
             infer::LateBoundRegion(_, br, infer::FnCall) => {
                 format!(" for lifetime parameter {}in function call", br_string(br))
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 da776f269d510..0aa1d65612ee6 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
@@ -2,14 +2,14 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
+use crate::infer::{SubregionOrigin, TypeTrace};
+use crate::traits::ObligationCauseCode;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
-use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::{
-    GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef,
-    TyKind,
-};
-use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor};
+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, TypeFoldable, TypeVisitor};
+use rustc_span::Span;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
@@ -27,6 +27,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             ) if **sub_r == RegionKind::ReStatic => {
                 (var_origin, sub_origin, sub_r, sup_origin, sup_r)
             }
+            RegionResolutionError::ConcreteFailure(
+                SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
+                sub_r,
+                sup_r,
+            ) if **sub_r == RegionKind::ReStatic => {
+                // This is for the implicit `'static` requirement coming from `impl dyn Trait {}`.
+                if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
+                    let param = self.find_param_with_region(sup_r, sub_r)?;
+                    let lifetime = if sup_r.has_name() {
+                        format!("lifetime `{}`", sup_r)
+                    } else {
+                        "an anonymous lifetime `'_`".to_string()
+                    };
+                    let mut err = struct_span_err!(
+                        tcx.sess,
+                        cause.span,
+                        E0759,
+                        "cannot infer an appropriate lifetime"
+                    );
+                    err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
+                    err.span_label(
+                        cause.span,
+                        "...is captured and required to live as long as `'static` here",
+                    );
+                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container) {
+                        err.emit();
+                        return Some(ErrorReported);
+                    } else {
+                        err.cancel();
+                    }
+                }
+                return None;
+            }
             _ => return None,
         };
         debug!(
@@ -96,7 +129,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             );
         }
 
-        self.find_impl_on_dyn_trait(&mut err, param.param_ty);
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
+            if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
+                self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container);
+            }
+        }
 
         let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
         debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
@@ -222,63 +259,86 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
     /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
     /// `'static` obligation. Find `impl` blocks that are implemented
-    fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool {
+    fn find_impl_on_dyn_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        ty: Ty<'_>,
+        container: &AssocItemContainer,
+    ) -> bool {
         let tcx = self.tcx();
+        let mut suggested = false;
 
         // Find the trait object types in the argument.
         let mut v = TraitObjectVisitor(vec![]);
         v.visit_ty(ty);
-        debug!("TraitObjectVisitor {:?}", v.0);
 
-        // Find all the `impl`s in the local scope that can be called on the type parameter.
-        // FIXME: this doesn't find `impl dyn Trait { /**/ }`.
+        let container_id = match container {
+            // When the obligation comes from an `impl Foo for dyn Bar {}`, we
+            // have the `DefId` of the `trait` itself, not the relevant `impl`
+            // block. Because of this, we have to look at all the `trait`s
+            // available, and filter out all that are not of `Foo` (this `def_id`)
+            // and not of `Bar` (the `filter_map` later in this method).
+            AssocItemContainer::TraitContainer(def_id) => def_id,
+
+            // When the obligation comes from an `impl dyn Trait {}`, we already
+            // have the `DefId` of the relevant `Item`, so we use it directly.
+            AssocItemContainer::ImplContainer(def_id) => {
+                if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
+                    tcx.hir().get_if_local(*def_id)
+                {
+                    for found_did in &v.0 {
+                        let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
+                        hir_v.visit_ty(self_ty);
+                        if let [span] = &hir_v.0[..] {
+                            err.span_suggestion_verbose(
+                                span.shrink_to_hi(),
+                                "this `impl` introduces an implicit `'static` requirement, \
+                                 consider changing it",
+                                " + '_".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                            suggested = true;
+                        }
+                    }
+                }
+                return suggested;
+            }
+        };
+
+        // Find all the `impl`s in the local scope that can be called on the type parameter. And
+        // retain all that are `impl`s of the trait that originated the `'static` obligation.
+        // This doesn't find `impl dyn Trait { /**/ }`, but that case is handled above.
         let impl_self_tys = tcx
             .all_traits(LOCAL_CRATE)
             .iter()
             .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
             .filter_map(|impl_node| {
                 let impl_did = tcx.hir().local_def_id(*impl_node);
-                if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
-                    tcx.hir().get_if_local(impl_did.to_def_id())
-                {
-                    Some(self_ty)
-                } else {
-                    None
+                match tcx.hir().get_if_local(impl_did.to_def_id()) {
+                    Some(Node::Item(Item {
+                        kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. },
+                        ..
+                    })) if of_trait.trait_def_id() == Some(*container_id) => Some(self_ty),
+                    _ => None,
                 }
             });
-        let mut suggested = false;
+
+        // Given all the `impl`s of the relevant `trait`, look for those that are implemented for
+        // the trait object in the `fn` parameter type.
         for self_ty in impl_self_tys {
-            if let TyKind::TraitObject(
-                poly_trait_refs,
-                Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
-            ) = self_ty.kind
-            {
-                for p in poly_trait_refs {
-                    if let PolyTraitRef {
-                        trait_ref:
-                            TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. },
-                        ..
-                    } = p
-                    {
-                        for found_did in &v.0 {
-                            if did == found_did {
-                                // We've found an `impl Foo for dyn Bar {}`.
-                                // FIXME: we should change this so it also works for
-                                // `impl Foo for Box<dyn Bar> {}`.
-                                err.span_suggestion_verbose(
-                                    self_ty.span.shrink_to_hi(),
-                                    "this `impl` introduces an implicit `'static` requirement, \
-                                     consider changing it",
-                                    " + '_".to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                suggested = true;
-                            }
-                        }
-                    }
+            for found_did in &v.0 {
+                let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
+                hir_v.visit_ty(self_ty);
+                if let [span] = &hir_v.0[..] {
+                    err.span_suggestion_verbose(
+                        span.shrink_to_hi(),
+                        "this `impl` introduces an implicit `'static` requirement, \
+                            consider changing it",
+                        " + '_".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                    suggested = true;
                 }
-                err.emit();
-                return Some(ErrorReported);
             }
         }
         suggested
@@ -301,3 +361,31 @@ impl TypeVisitor<'_> for TraitObjectVisitor {
         }
     }
 }
+
+/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
+struct HirTraitObjectVisitor(Vec<Span>, DefId);
+
+impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor {
+    type Map = ErasedMap<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
+        match t.kind {
+            TyKind::TraitObject(
+                poly_trait_refs,
+                Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
+            ) => {
+                for ptr in poly_trait_refs {
+                    if Some(self.1) == ptr.trait_ref.trait_def_id() {
+                        self.0.push(ptr.span);
+                    }
+                }
+            }
+            _ => {}
+        }
+        walk_ty(self, t);
+    }
+}
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
index fa999abb1a86c..28e9dd90cfd67 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
@@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::{self, DefIdTree, Region, Ty};
 use rustc_span::Span;
 
-// The struct contains the information about the anonymous region
-// we are searching for.
+/// Information about the anonymous region we are searching for.
 #[derive(Debug)]
 pub(super) struct AnonymousParamInfo<'tcx> {
-    // the parameter corresponding to the anonymous region
+    /// The parameter corresponding to the anonymous region.
     pub param: &'tcx hir::Param<'tcx>,
-    // the type corresponding to the anonymopus region parameter
+    /// The type corresponding to the anonymous region parameter.
     pub param_ty: Ty<'tcx>,
-    // the ty::BoundRegion corresponding to the anonymous region
+    /// The ty::BoundRegion corresponding to the anonymous region.
     pub bound_region: ty::BoundRegion,
-    // param_ty_span contains span of parameter type
+    /// The `Span` of the parameter type.
     pub param_ty_span: Span,
-    // corresponds to id the argument is the first parameter
-    // in the declaration
+    /// Signals that the argument is the first parameter in the declaration.
     pub is_first: bool,
 }
 
diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs
index 37883fcb07468..3744ad5d0324a 100644
--- a/src/librustc_infer/infer/mod.rs
+++ b/src/librustc_infer/infer/mod.rs
@@ -463,7 +463,7 @@ pub enum RegionVariableOrigin {
     AddrOfRegion(Span),
 
     /// Regions created as part of an autoref of a method receiver
-    Autoref(Span),
+    Autoref(Span, ty::AssocItem),
 
     /// Regions created as part of an automatic coercion
     Coercion(Span),
@@ -1800,15 +1800,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
 impl RegionVariableOrigin {
     pub fn span(&self) -> Span {
         match *self {
-            MiscVariable(a) => a,
-            PatternRegion(a) => a,
-            AddrOfRegion(a) => a,
-            Autoref(a) => a,
-            Coercion(a) => a,
-            EarlyBoundRegion(a, ..) => a,
-            LateBoundRegion(a, ..) => a,
+            MiscVariable(a)
+            | PatternRegion(a)
+            | AddrOfRegion(a)
+            | Autoref(a, _)
+            | Coercion(a)
+            | EarlyBoundRegion(a, ..)
+            | LateBoundRegion(a, ..)
+            | UpvarRegion(_, a) => a,
             BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
-            UpvarRegion(_, a) => a,
             NLL(..) => bug!("NLL variable used with `span`"),
         }
     }
diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs
index 0cd6585163c4e..bacb7fa153e43 100644
--- a/src/librustc_infer/lib.rs
+++ b/src/librustc_infer/lib.rs
@@ -13,6 +13,7 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bindings_after_at)]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs
index c15c31a53f0c9..c066ea831b298 100644
--- a/src/librustc_middle/traits/mod.rs
+++ b/src/librustc_middle/traits/mod.rs
@@ -300,6 +300,8 @@ pub enum ObligationCauseCode<'tcx> {
     /// Method receiver
     MethodReceiver,
 
+    UnifyReceiver(Rc<ty::AssocItem>),
+
     /// `return` with no expression
     ReturnNoExpression,
 
diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs
index 334462790edbc..61ef0821733e8 100644
--- a/src/librustc_middle/traits/structural_impls.rs
+++ b/src/librustc_middle/traits/structural_impls.rs
@@ -213,6 +213,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
             super::StartFunctionType => Some(super::StartFunctionType),
             super::IntrinsicType => Some(super::IntrinsicType),
             super::MethodReceiver => Some(super::MethodReceiver),
+            super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())),
             super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
             super::TrivialBound => Some(super::TrivialBound),
         }
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 21745977b04b1..3b83ba8a4a71b 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -136,7 +136,7 @@ pub struct ResolverOutputs {
     pub extern_prelude: FxHashMap<Symbol, bool>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
 pub enum AssocItemContainer {
     TraitContainer(DefId),
     ImplContainer(DefId),
@@ -184,7 +184,7 @@ pub enum ImplPolarity {
     Reservation,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
 pub struct AssocItem {
     pub def_id: DefId,
     #[stable_hasher(project(name))]
@@ -199,7 +199,7 @@ pub struct AssocItem {
     pub fn_has_self_parameter: bool,
 }
 
-#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
 pub enum AssocKind {
     Const,
     Fn,
@@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
 pub enum Visibility {
     /// Visible everywhere (including in other crates).
     Public,
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 0a6fb72ca51ea..e94b44d879533 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             | ObligationCauseCode::IntrinsicType
             | ObligationCauseCode::MethodReceiver
             | ObligationCauseCode::ReturnNoExpression
+            | ObligationCauseCode::UnifyReceiver(_)
             | ObligationCauseCode::MiscObligation => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 96248e18aaf87..58cbe8b2479d6 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -6,6 +6,7 @@ use crate::hir::def_id::DefId;
 use crate::hir::GenericArg;
 use rustc_hir as hir;
 use rustc_infer::infer::{self, InferOk};
+use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
@@ -15,6 +16,7 @@ use rustc_span::Span;
 use rustc_trait_selection::traits;
 
 use std::ops::Deref;
+use std::rc::Rc;
 
 struct ConfirmContext<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -91,7 +93,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // signature (which is also done during probing).
         let method_sig_rcvr =
             self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
-        self.unify_receivers(self_ty, method_sig_rcvr);
+        debug!(
+            "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
+            self_ty, method_sig_rcvr, method_sig, method_predicates
+        );
+        self.unify_receivers(self_ty, method_sig_rcvr, &pick);
 
         let (method_sig, method_predicates) =
             self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
@@ -150,7 +156,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
 
         if let Some(mutbl) = pick.autoref {
-            let region = self.next_region_var(infer::Autoref(self.span));
+            let region = self.next_region_var(infer::Autoref(self.span, pick.item));
             target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
             let mutbl = match mutbl {
                 hir::Mutability::Not => AutoBorrowMutability::Not,
@@ -334,8 +340,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         )
     }
 
-    fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
-        match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) {
+    fn unify_receivers(
+        &mut self,
+        self_ty: Ty<'tcx>,
+        method_self_ty: Ty<'tcx>,
+        pick: &probe::Pick<'tcx>,
+    ) {
+        debug!(
+            "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
+            self_ty, method_self_ty, self.span, pick
+        );
+        let cause = self.cause(self.span, ObligationCauseCode::UnifyReceiver(Rc::new(pick.item)));
+        match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs
deleted file mode 100644
index dd53ee06ff5ee..0000000000000
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-trait OtherTrait<'a> {}
-impl<'a> OtherTrait<'a> for &'a () {}
-
-trait ObjectTrait {}
-
-impl dyn ObjectTrait {
-    fn use_self(&self) -> &() { panic!() }
-}
-
-fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-    val.use_self() //~ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr
deleted file mode 100644
index 4618b540c70ee..0000000000000
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9
-   |
-LL |     val.use_self()
-   |         ^^^^^^^^ lifetime mismatch
-   |
-   = note: expected reference `&(dyn ObjectTrait + 'static)`
-              found reference `&(dyn ObjectTrait + 'a)`
-note: the lifetime `'a` as defined on the function body at 10:11...
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11
-   |
-LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-   |           ^^
-   = note: ...does not necessarily outlive the static lifetime
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
index dfe475d3c0694..62cf9b989bb4d 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
@@ -9,10 +9,12 @@ mod foo {
     trait MyTrait {
         fn use_self(&self) -> &();
     }
+    trait Irrelevant {}
 
     impl MyTrait for dyn ObjectTrait + '_ {
         fn use_self(&self) -> &() { panic!() }
     }
+    impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
         val.use_self() //~ ERROR cannot infer an appropriate lifetime
@@ -24,14 +26,48 @@ mod bar {
     trait MyTrait {
         fn use_self(&self) -> &();
     }
+    trait Irrelevant {}
 
     impl MyTrait for dyn ObjectTrait + '_ {
         fn use_self(&self) -> &() { panic!() }
     }
+    impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
         val.use_self() //~ ERROR cannot infer an appropriate lifetime
     }
 }
 
+mod baz {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for Box<dyn ObjectTrait + '_> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for Box<dyn ObjectTrait> {}
+
+    fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+mod bat {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+
+    impl dyn ObjectTrait + '_ {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
new file mode 100644
index 0000000000000..00f65a2348935
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
@@ -0,0 +1,22 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         val.use_self()
+   |         ^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         val.use_self()
+   |         ^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
index 85e6c2993b9b1..28a599d12bfd1 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -9,10 +9,12 @@ mod foo {
     trait MyTrait {
         fn use_self(&self) -> &();
     }
+    trait Irrelevant {}
 
     impl MyTrait for dyn ObjectTrait {
         fn use_self(&self) -> &() { panic!() }
     }
+    impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
         val.use_self() //~ ERROR cannot infer an appropriate lifetime
@@ -24,14 +26,48 @@ mod bar {
     trait MyTrait {
         fn use_self(&self) -> &();
     }
+    trait Irrelevant {}
 
     impl MyTrait for dyn ObjectTrait {
         fn use_self(&self) -> &() { panic!() }
     }
+    impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
         val.use_self() //~ ERROR cannot infer an appropriate lifetime
     }
 }
 
+mod baz {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for Box<dyn ObjectTrait> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for Box<dyn ObjectTrait> {}
+
+    fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+mod bat {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+
+    impl dyn ObjectTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
 fn main() {}
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 6780459adbeac..1a03590febe46 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
@@ -1,5 +1,5 @@
 error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
    |                        ------------------- this data with lifetime `'a`...
@@ -12,7 +12,20 @@ LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
 
 error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13
+   |
+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
+   |
+help: this `impl` introduces an implicit `'static` requirement, consider changing it
+   |
+LL |     impl dyn ObjectTrait + '_ {
+   |                          ^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
    |                        ------------------- this data with lifetime `'a`...
@@ -24,6 +37,19 @@ help: this `impl` introduces an implicit `'static` requirement, consider changin
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
 
-error: aborting due to 2 previous errors
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13
+   |
+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
+   |
+help: this `impl` introduces an implicit `'static` requirement, consider changing it
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {
+   |                                          ^^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0759`.

From 3f5c7f2e5ef86164a3b768338d429aa73387efa1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 28 Jun 2020 18:07:26 -0700
Subject: [PATCH 3/8] Add more context to diagnostic

---
 .../nice_region_error/static_impl_trait.rs    | 78 +++++++++++++++----
 ...yn-trait-with-implicit-static-bound.stderr | 36 ++++++++-
 2 files changed, 96 insertions(+), 18 deletions(-)

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 0aa1d65612ee6..36d354ea777a4 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
@@ -8,8 +8,10 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorRepor
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 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, TypeFoldable, TypeVisitor};
-use rustc_span::Span;
+use rustc_middle::ty::{
+    self, AssocItem, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor,
+};
+use rustc_span::{MultiSpan, Span};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
@@ -51,7 +53,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                         cause.span,
                         "...is captured and required to live as long as `'static` here",
                     );
-                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container) {
+                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) {
                         err.emit();
                         return Some(ErrorReported);
                     } else {
@@ -131,7 +133,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
         if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
             if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
-                self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container);
+                self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc);
             }
         }
 
@@ -263,7 +265,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         &self,
         err: &mut DiagnosticBuilder<'_>,
         ty: Ty<'_>,
-        container: &AssocItemContainer,
+        assoc: &AssocItem,
     ) -> bool {
         let tcx = self.tcx();
         let mut suggested = false;
@@ -272,7 +274,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let mut v = TraitObjectVisitor(vec![]);
         v.visit_ty(ty);
 
-        let container_id = match container {
+        let container_id = match assoc.container {
             // When the obligation comes from an `impl Foo for dyn Bar {}`, we
             // have the `DefId` of the `trait` itself, not the relevant `impl`
             // block. Because of this, we have to look at all the `trait`s
@@ -284,16 +286,35 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             // have the `DefId` of the relevant `Item`, so we use it directly.
             AssocItemContainer::ImplContainer(def_id) => {
                 if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
-                    tcx.hir().get_if_local(*def_id)
+                    tcx.hir().get_if_local(def_id)
                 {
                     for found_did in &v.0 {
                         let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
                         hir_v.visit_ty(self_ty);
                         if let [span] = &hir_v.0[..] {
+                            let mut multi_span: MultiSpan = vec![*span].into();
+                            multi_span.push_span_label(
+                                *span,
+                                "this trait object has an implicit `'static` lifetime requirement"
+                                    .to_string(),
+                            );
+                            multi_span.push_span_label(
+                                assoc.ident.span,
+                                "the `'static` requirement is introduced when calling this method"
+                                    .to_string(),
+                            );
+                            err.span_note(
+                                multi_span,
+                                &format!(
+                                    "when using method `{}` on `{}`, an implicit `'static` \
+                                     requirement is introduced",
+                                    assoc.ident,
+                                    tcx.def_path_str(*found_did),
+                                ),
+                            );
                             err.span_suggestion_verbose(
                                 span.shrink_to_hi(),
-                                "this `impl` introduces an implicit `'static` requirement, \
-                                 consider changing it",
+                                "consider relaxing the implicit `'static` requirement",
                                 " + '_".to_string(),
                                 Applicability::MaybeIncorrect,
                             );
@@ -316,24 +337,53 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 let impl_did = tcx.hir().local_def_id(*impl_node);
                 match tcx.hir().get_if_local(impl_did.to_def_id()) {
                     Some(Node::Item(Item {
-                        kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. },
+                        kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), items, .. },
                         ..
-                    })) if of_trait.trait_def_id() == Some(*container_id) => Some(self_ty),
+                    })) if of_trait.trait_def_id() == Some(container_id) => Some((
+                        self_ty,
+                        // Get the ident of the method, in order to use its `Span`.
+                        items
+                            .iter()
+                            .filter(|item| item.ident == assoc.ident)
+                            .map(|item| item.ident)
+                            .next()
+                            .unwrap_or(assoc.ident),
+                    )),
                     _ => None,
                 }
             });
 
         // Given all the `impl`s of the relevant `trait`, look for those that are implemented for
         // the trait object in the `fn` parameter type.
-        for self_ty in impl_self_tys {
+        for (self_ty, method) in impl_self_tys {
             for found_did in &v.0 {
                 let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
                 hir_v.visit_ty(self_ty);
                 if let [span] = &hir_v.0[..] {
+                    let mut multi_span: MultiSpan = vec![*span].into();
+                    multi_span.push_span_label(
+                        *span,
+                        "this trait object has an implicit `'static` lifetime requirement"
+                            .to_string(),
+                    );
+                    multi_span.push_span_label(
+                        method.span,
+                        "the `'static` requirement is introduced when calling this method"
+                            .to_string(),
+                    );
+                    err.span_note(
+                        multi_span,
+                        &format!(
+                            "when using method `{}` of trait `{}` on `{}`, an implicit `'static` \
+                             requirement is introduced",
+                            method,
+                            tcx.def_path_str(container_id),
+                            tcx.def_path_str(*found_did),
+                        ),
+                    );
                     err.span_suggestion_verbose(
                         span.shrink_to_hi(),
-                        "this `impl` introduces an implicit `'static` requirement, \
-                            consider changing it",
+                        "consider relaxing the implicit `'static` requirement",
                         " + '_".to_string(),
                         Applicability::MaybeIncorrect,
                     );
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 1a03590febe46..8f8fd9dc32402 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
@@ -6,7 +6,14 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-help: this `impl` introduces an implicit `'static` requirement, consider changing it
+note: when using method `use_self` of trait `foo::MyTrait` on `foo::ObjectTrait`, an implicit `'static` requirement is introduced
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26
+   |
+LL |     impl MyTrait for dyn ObjectTrait {
+   |                          ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- the `'static` requirement is introduced when calling this method
+help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
@@ -19,7 +26,14 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-help: this `impl` introduces an implicit `'static` requirement, consider changing it
+note: when using method `use_self` on `bat::ObjectTrait`, an implicit `'static` requirement is introduced
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
+   |
+LL |     impl dyn ObjectTrait {
+   |              ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- the `'static` requirement is introduced when calling this method
+help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl dyn ObjectTrait + '_ {
    |                          ^^^^
@@ -32,7 +46,14 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-help: this `impl` introduces an implicit `'static` requirement, consider changing it
+note: when using method `use_self` of trait `bar::MyTrait` on `bar::ObjectTrait`, an implicit `'static` requirement is introduced
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
+   |
+LL |     impl MyTrait for dyn ObjectTrait {
+   |                          ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- the `'static` requirement is introduced when calling this method
+help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
@@ -45,7 +66,14 @@ LL |     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-help: this `impl` introduces an implicit `'static` requirement, consider changing it
+note: when using method `use_self` of trait `baz::MyTrait` on `baz::ObjectTrait`, an implicit `'static` requirement is introduced
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait> {
+   |                              ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- the `'static` requirement is introduced when calling this method
+help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {
    |                                          ^^^^

From 8f749710b4477f2d93c89b67c012d87d56de1bc0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 29 Jun 2020 11:14:42 -0700
Subject: [PATCH 4/8] Further tweak wording of E0759 and introduce E0767

---
 src/librustc_error_codes/error_codes.rs       |   1 +
 .../nice_region_error/static_impl_trait.rs    | 107 +++++++++++++-----
 ...ject-fn-ret-contravariant.transmute.stderr |   2 +-
 .../project-fn-ret-invariant.transmute.stderr |   2 +-
 src/test/ui/async-await/issues/issue-62097.rs |   2 +-
 .../ui/async-await/issues/issue-62097.stderr  |   2 +-
 .../impl-header-lifetime-elision/dyn-trait.rs |   2 +-
 .../dyn-trait.stderr                          |   2 +-
 ...t_outlive_least_region_or_bound.nll.stderr |  16 +--
 .../must_outlive_least_region_or_bound.rs     |  32 ++----
 .../must_outlive_least_region_or_bound.stderr |  58 +++++-----
 .../static-return-lifetime-infered.nll.stderr |   2 +-
 .../static-return-lifetime-infered.rs         |   6 +-
 .../static-return-lifetime-infered.stderr     |   8 +-
 src/test/ui/issues/issue-16922.rs             |   3 +-
 src/test/ui/issues/issue-16922.stderr         |   2 +-
 .../constant-in-expr-inherent-1.stderr        |   2 +-
 .../object-lifetime-default-from-box-error.rs |   2 +-
 ...ect-lifetime-default-from-box-error.stderr |   2 +-
 .../region-object-lifetime-in-coercion.rs     |   6 +-
 .../region-object-lifetime-in-coercion.stderr |   6 +-
 src/test/ui/regions/regions-addr-of-self.rs   |   2 +-
 .../ui/regions/regions-addr-of-self.stderr    |   2 +-
 .../regions-close-object-into-object-2.rs     |   2 +-
 .../regions-close-object-into-object-2.stderr |   2 +-
 .../regions-close-object-into-object-4.rs     |   2 +-
 .../regions-close-object-into-object-4.stderr |   2 +-
 .../ui/regions/regions-proc-bound-capture.rs  |   2 +-
 .../regions/regions-proc-bound-capture.stderr |   2 +-
 ...elf_types_pin_lifetime_impl_trait-async.rs |   2 +-
 ...types_pin_lifetime_impl_trait-async.stderr |   2 +-
 ...rary_self_types_pin_lifetime_impl_trait.rs |   2 +-
 ..._self_types_pin_lifetime_impl_trait.stderr |   2 +-
 ...dyn-trait-with-implicit-static-bound.fixed |  29 ++++-
 ...rait-with-implicit-static-bound.nll.stderr |  12 +-
 ...on-dyn-trait-with-implicit-static-bound.rs |  29 ++++-
 ...yn-trait-with-implicit-static-bound.stderr |  64 +++++++----
 .../missing-lifetimes-in-signature.rs         |   2 +-
 .../missing-lifetimes-in-signature.stderr     |   2 +-
 .../trait-object-nested-in-impl-trait.rs      |   8 +-
 .../trait-object-nested-in-impl-trait.stderr  |   8 +-
 .../dyn-trait-underscore.rs                   |   2 +-
 .../dyn-trait-underscore.stderr               |   2 +-
 43 files changed, 280 insertions(+), 167 deletions(-)

diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index bbbd8359f0126..a5d4adae8dba4 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -632,4 +632,5 @@ E0770: include_str!("./error_codes/E0770.md"),
     E0755, // `#[ffi_pure]` is only allowed on foreign functions
     E0756, // `#[ffi_const]` is only allowed on foreign functions
     E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+    E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
 }
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 36d354ea777a4..9fa905cb5abe9 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
@@ -45,13 +45,31 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     let mut err = struct_span_err!(
                         tcx.sess,
                         cause.span,
-                        E0759,
-                        "cannot infer an appropriate lifetime"
+                        E0767,
+                        "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
+                         requirement",
+                        param
+                            .param
+                            .pat
+                            .simple_ident()
+                            .map(|s| format!("`{}`", s))
+                            .unwrap_or_else(|| "`fn` parameter".to_string()),
+                        lifetime,
+                        assoc.ident,
                     );
                     err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
                     err.span_label(
                         cause.span,
-                        "...is captured and required to live as long as `'static` here",
+                        &format!(
+                            "...is captured and required to live as long as `'static` here \
+                             because of an implicit lifetime bound on the {}",
+                            match assoc.container {
+                                AssocItemContainer::TraitContainer(id) =>
+                                    format!("`impl` of `{}`", tcx.def_path_str(id)),
+                                AssocItemContainer::ImplContainer(_) =>
+                                    "inherent `impl`".to_string(),
+                            },
+                        ),
                     );
                     if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) {
                         err.emit();
@@ -78,10 +96,49 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         } else {
             ("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
         };
-        let mut err = struct_span_err!(tcx.sess, sp, E0759, "cannot infer an appropriate lifetime");
+        let param_name = param
+            .param
+            .pat
+            .simple_ident()
+            .map(|s| format!("`{}`", s))
+            .unwrap_or_else(|| "`fn` parameter".to_string());
+        let mut err = struct_span_err!(
+            tcx.sess,
+            sp,
+            E0759,
+            "{} has {} but it needs to satisfy a `'static` lifetime requirement",
+            param_name,
+            lifetime,
+        );
         err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
         debug!("try_report_static_impl_trait: param_info={:?}", param);
 
+        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
+
+        let mut postfix = String::new();
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
+            if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
+                if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc)
+                    && fn_returns.is_empty()
+                {
+                    err.code(rustc_errors::error_code!(E0767));
+                    err.set_primary_message(&format!(
+                        "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
+                         requirement",
+                        param_name, lifetime, assoc.ident,
+                    ));
+                    postfix = format!(
+                        " because of an implicit lifetime on the {}",
+                        match assoc.container {
+                            AssocItemContainer::TraitContainer(id) =>
+                                format!("`impl` of `{}`", tcx.def_path_str(id)),
+                            AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(),
+                        },
+                    );
+                }
+            }
+        }
+
         // 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
@@ -108,36 +165,35 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 //    |           ----                               ^
                 err.span_label(
                     sup_origin.span(),
-                    "...is captured here, requiring it to live as long as `'static`",
+                    &format!(
+                        "...is captured here, requiring it to live as long as `'static`{}",
+                        postfix
+                    ),
                 );
             } 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",
+                        &format!("...and is required to live as long as `'static` here{}", postfix),
                     );
                 } else {
                     err.span_label(
                         return_sp,
-                        "...and is required to live as long as `'static` here",
+                        &format!("...and is required to live as long as `'static` here{}", postfix),
                     );
                 }
             }
         } else {
             err.span_label(
                 return_sp,
-                "...is captured and required to live as long as `'static` here",
+                &format!(
+                    "...is captured and required to live as long as `'static` here{}",
+                    postfix
+                ),
             );
         }
 
-        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
-            if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
-                self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc);
-            }
-        }
-
-        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
         debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
         // FIXME: account for the need of parens in `&(dyn Trait + '_)`
         let consider = "consider changing the";
@@ -295,20 +351,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             let mut multi_span: MultiSpan = vec![*span].into();
                             multi_span.push_span_label(
                                 *span,
-                                "this trait object has an implicit `'static` lifetime requirement"
-                                    .to_string(),
+                                "this has an implicit `'static` lifetime requirement".to_string(),
                             );
                             multi_span.push_span_label(
                                 assoc.ident.span,
-                                "the `'static` requirement is introduced when calling this method"
+                                "`'static` requirement is introduced when calling this method"
                                     .to_string(),
                             );
                             err.span_note(
                                 multi_span,
                                 &format!(
-                                    "when using method `{}` on `{}`, an implicit `'static` \
-                                     requirement is introduced",
-                                    assoc.ident,
+                                    "`{}`'s inherent `impl` has a `'static` requirement",
                                     tcx.def_path_str(*found_did),
                                 ),
                             );
@@ -363,22 +416,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     let mut multi_span: MultiSpan = vec![*span].into();
                     multi_span.push_span_label(
                         *span,
-                        "this trait object has an implicit `'static` lifetime requirement"
-                            .to_string(),
+                        "this has an implicit `'static` lifetime requirement".to_string(),
                     );
                     multi_span.push_span_label(
                         method.span,
-                        "the `'static` requirement is introduced when calling this method"
-                            .to_string(),
+                        "`'static` requirement is introduced when calling this method".to_string(),
                     );
                     err.span_note(
                         multi_span,
                         &format!(
-                            "when using method `{}` of trait `{}` on `{}`, an implicit `'static` \
-                             requirement is introduced",
-                            method,
-                            tcx.def_path_str(container_id),
+                            "`{}`'s `impl` of `{}` has an implicit `'static` requirement",
                             tcx.def_path_str(*found_did),
+                            tcx.def_path_str(container_id),
                         ),
                     );
                     err.span_suggestion_verbose(
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 36812d3c0441e..0be9b37263a48 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
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/project-fn-ret-contravariant.rs:38:8
    |
 LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
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 9cec0780b3ca8..0a44864b24955 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
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/project-fn-ret-invariant.rs:49:9
    |
 LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
diff --git a/src/test/ui/async-await/issues/issue-62097.rs b/src/test/ui/async-await/issues/issue-62097.rs
index ea482d3667e2b..66ebbd83ffa9e 100644
--- a/src/test/ui/async-await/issues/issue-62097.rs
+++ b/src/test/ui/async-await/issues/issue-62097.rs
@@ -9,7 +9,7 @@ where
 struct Struct;
 
 impl Struct {
-    pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer
+    pub async fn run_dummy_fn(&self) { //~ ERROR E0759
         foo(|| self.bar()).await;
     }
 
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index 0f58b158904db..56a28d904b91d 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/issue-62097.rs:12:31
    |
 LL |     pub async fn run_dummy_fn(&self) {
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs
index d4ad706d01bc2..89210fdf137e0 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.rs
@@ -17,7 +17,7 @@ fn static_val<T: StaticTrait>(_: T) {
 }
 
 fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
-    static_val(x); //~ ERROR cannot infer
+    static_val(x); //~ ERROR E0759
 }
 
 fn not_static_val<T: NotStaticTrait>(_: T) {
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 397cb3750c266..b3bef677d19c1 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/dyn-trait.rs:20:16
    |
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
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 3b339c5c3d7fc..4372de245078f 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
@@ -12,7 +12,7 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                       ^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:5:32
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             --                 ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
@@ -26,7 +26,7 @@ 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:9:46
+  --> $DIR/must_outlive_least_region_or_bound.rs:7:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               -                              ^ returning this value requires that `'1` must outlive `'static`
@@ -36,7 +36,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    = help: consider replacing `'1` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+  --> $DIR/must_outlive_least_region_or_bound.rs:9: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`
@@ -45,7 +45,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    = 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
+  --> $DIR/must_outlive_least_region_or_bound.rs:11:41
    |
 LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
    |               ----                      ^ lifetime `'a` required
@@ -53,7 +53,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
    |               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:30:24
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:24
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               -        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
@@ -61,7 +61,7 @@ LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               let's call the lifetime of this reference `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:37:69
+  --> $DIR/must_outlive_least_region_or_bound.rs:28: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`
@@ -70,7 +70,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:42:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:32: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`
@@ -80,7 +80,7 @@ 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:47:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:37:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                                   ^^^^^^^^^^^^^^^^^^^^
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 9bf86fa66cded..51f488e45a6f3 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
@@ -1,41 +1,31 @@
 use std::fmt::Debug;
 
-fn elided(x: &i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759
 
-fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759
 
-fn elided2(x: &i32) -> impl Copy + 'static { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759
 
-fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } //~ ERROR E0759
 
 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 elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } //~ ERROR E0759
 
-fn explicit3<'a>(x: &'a 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 E0759
 
-fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
 
-fn explicit4<'a>(x: &'a 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 E0759
 
-fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
-//~^ ERROR cannot infer an appropriate lifetime
-//~| ERROR cannot infer an appropriate lifetime
+fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~ ERROR E0759
+//~^ ERROR E0759
 
 trait LifetimeTrait<'a> {}
 impl<'a> LifetimeTrait<'a> for &'a i32 {}
 
-fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERROR E0759
 
 // Tests that a closure type containing 'b cannot be returned from a type where
 // only 'a was expected.
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 ffadcaae08e05..b040889217e47 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,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
@@ -16,8 +16,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:5:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |                    -------                 ^ ...is captured here...
@@ -25,7 +25,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |                    this data with lifetime `'a`...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:5:32
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |                                ^^^^^^^^^
@@ -34,8 +34,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                          ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:7:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               ----                           ^ ...is captured here...
@@ -43,7 +43,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               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
+  --> $DIR/must_outlive_least_region_or_bound.rs:7:24
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -56,8 +56,8 @@ 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
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:55
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |                     -------                           ^ ...is captured here...
@@ -65,7 +65,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |                     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
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:33
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |                                 ^^^^^^^^^^^^^^^^^^^
@@ -79,15 +79,15 @@ 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
+  --> $DIR/must_outlive_least_region_or_bound.rs:11: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:30:65
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:22: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`
@@ -101,14 +101,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
    |                                                    ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:30:69
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:69
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               ---- this data with an anonymous lifetime `'_`...     ^ ...is captured here...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:30:41
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:41
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |                                         ^^^^^^^^^^
@@ -121,14 +121,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
    |                                                    ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:37:69
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:28:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |                      ------- this data with lifetime `'a`...        ^ ...is captured here...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:37:34
+  --> $DIR/must_outlive_least_region_or_bound.rs:28:34
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -142,7 +142,7 @@ 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:42:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:32:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                                                 -------     ^^^^^^^^^^^^^^^^
@@ -151,15 +151,15 @@ 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:47:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:37: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[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:14:50
    |
 LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
    |               ----                               ^ ...is captured here, requiring it to live as long as `'static`
@@ -171,8 +171,8 @@ help: to declare that the trait object captures data from argument `x`, you can
 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
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:16: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`
@@ -184,8 +184,8 @@ help: to declare that the trait object captures data from argument `x`, you can
 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
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:18:60
    |
 LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
    |               ----                                         ^ ...is captured here, requiring it to live as long as `'static`
@@ -201,8 +201,8 @@ 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
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:20: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`
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
index 123ea6af6b019..65178cc9d24c2 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
@@ -12,7 +12,7 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/static-return-lifetime-infered.rs:10:37
+  --> $DIR/static-return-lifetime-infered.rs:9:37
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    --               ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
index 96f3652c226ea..518c52f5de4d7 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
@@ -4,13 +4,11 @@ struct A {
 
 impl A {
     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-        self.x.iter().map(|a| a.0)
+        self.x.iter().map(|a| a.0) //~ ERROR E0759
     }
-    //~^^ ERROR cannot infer an appropriate lifetime
     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-        self.x.iter().map(|a| a.0)
+        self.x.iter().map(|a| a.0) //~ ERROR E0759
     }
-    //~^^ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() {}
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 df0db6e4fc6df..7c289b388223a 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/static-return-lifetime-infered.rs:7:16
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
@@ -18,8 +18,8 @@ help: to declare that the `impl Trait` captures data from argument `self`, you c
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/static-return-lifetime-infered.rs:11:16
+error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/static-return-lifetime-infered.rs:10:16
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                        -------- this data with lifetime `'a`...
@@ -29,7 +29,7 @@ LL |         self.x.iter().map(|a| a.0)
    |         ...is captured here...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/static-return-lifetime-infered.rs:10:37
+  --> $DIR/static-return-lifetime-infered.rs:9:37
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs
index 827163ef83cf7..f048ccd2427cb 100644
--- a/src/test/ui/issues/issue-16922.rs
+++ b/src/test/ui/issues/issue-16922.rs
@@ -1,8 +1,7 @@
 use std::any::Any;
 
 fn foo<T: Any>(value: &T) -> Box<dyn Any> {
-    Box::new(value) as Box<dyn Any>
-    //~^ ERROR cannot infer an appropriate lifetime
+    Box::new(value) as Box<dyn Any> //~ ERROR E0759
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 919594fc9af4b..6decc751321f9 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `value` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/issue-16922.rs:4:14
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
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 f823f69c76f67..1931934a2112a 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
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/constant-in-expr-inherent-1.rs:8:5
    |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
index 708ab1cf38297..4a2665d8e1694 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
@@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
     // is illegal.
 
-    ss.r //~ ERROR cannot infer an appropriate lifetime
+    ss.r //~ ERROR E0759
 }
 
 fn store(ss: &mut SomeStruct, b: Box<dyn SomeTrait>) {
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 1b1e0d9610724..70b99ef7869ca 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,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `ss` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
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 5d199149c39b8..9d3f485e31438 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -5,18 +5,18 @@ 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 cannot infer an appropriate lifetime
+    let x: Box<dyn Foo + 'static> = Box::new(v); //~ ERROR E0759
     x
 }
 
 fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(v) //~ ERROR E0759
 }
 
 fn c(v: &[u8]) -> Box<dyn Foo> {
     // same as previous case due to RFC 599
 
-    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(v) //~ ERROR E0759
 }
 
 fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
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 7f5a3a47976c7..63fea1f41626d 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/region-object-lifetime-in-coercion.rs:8:46
    |
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
@@ -15,7 +15,7 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn a(v: &'static [u8]) -> Box<dyn Foo + 'static> {
    |         ^^^^^^^^^^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/region-object-lifetime-in-coercion.rs:13:14
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
@@ -32,7 +32,7 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn b(v: &'static [u8]) -> Box<dyn Foo + 'static> {
    |         ^^^^^^^^^^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/region-object-lifetime-in-coercion.rs:19:14
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
diff --git a/src/test/ui/regions/regions-addr-of-self.rs b/src/test/ui/regions/regions-addr-of-self.rs
index 647212407fc8a..4eb1b275f163e 100644
--- a/src/test/ui/regions/regions-addr-of-self.rs
+++ b/src/test/ui/regions/regions-addr-of-self.rs
@@ -4,7 +4,7 @@ struct Dog {
 
 impl Dog {
     pub fn chase_cat(&mut self) {
-        let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer
+        let p: &'static mut usize = &mut self.cats_chased; //~ ERROR E0759
         *p += 1;
     }
 
diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr
index c15a933379c85..738691fd695eb 100644
--- a/src/test/ui/regions/regions-addr-of-self.stderr
+++ b/src/test/ui/regions/regions-addr-of-self.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/regions-addr-of-self.rs:7:37
    |
 LL |     pub fn chase_cat(&mut self) {
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.rs b/src/test/ui/regions/regions-close-object-into-object-2.rs
index 2364ba2728600..7144ab5a24c51 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.rs
+++ b/src/test/ui/regions/regions-close-object-into-object-2.rs
@@ -7,7 +7,7 @@ trait X { }
 impl<'a, T> X for B<'a, T> {}
 
 fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
-    box B(&*v) as Box<dyn X> //~ ERROR cannot infer
+    box B(&*v) as Box<dyn X> //~ ERROR E0759
 }
 
 fn main() { }
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 114e4052aae09..aab7ce993aa3c 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,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $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> {
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.rs b/src/test/ui/regions/regions-close-object-into-object-4.rs
index d531077043686..4c087f264f92b 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.rs
+++ b/src/test/ui/regions/regions-close-object-into-object-4.rs
@@ -7,7 +7,7 @@ trait X { }
 impl<'a, T> X for B<'a, T> {}
 
 fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
-    box B(&*v) as Box<dyn X> //~ ERROR cannot infer
+    box B(&*v) as Box<dyn X> //~ ERROR E0759
 }
 
 fn main() {}
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 850d81940791f..90f807a41c562 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,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $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> {
diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs
index 8617c0e9da8f7..55d964ac53405 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.rs
+++ b/src/test/ui/regions/regions-proc-bound-capture.rs
@@ -6,7 +6,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box<dyn FnMut()->(isize) + 'a> {
 
 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 cannot infer an appropriate lifetime
+    Box::new(move || { *x }) //~ ERROR E0759
 }
 
 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 67eee3bb6e281..e76073f4f6b13 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/regions-proc-bound-capture.rs:9:14
    |
 LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs
index 0afe631f1e3fc..43998ca8c5784 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs
@@ -6,7 +6,7 @@ struct Foo;
 
 impl Foo {
     async fn f(self: Pin<&Self>) -> impl Clone { self }
-    //~^ ERROR cannot infer an appropriate lifetime
+    //~^ ERROR E0759
 }
 
 fn main() {
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 f2fbb0ba7d755..9cd0fd328ffa0 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,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
index 5054568b18970..04935fc52ab9e 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
@@ -3,7 +3,7 @@ use std::pin::Pin;
 struct Foo;
 
 impl Foo {
-    fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime
+    fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR E0759
 }
 
 fn main() {
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 2e10ab3d3f9b8..cb9d5b56dbc5c 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,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
index 62cf9b989bb4d..832b185e619fa 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
@@ -17,7 +17,7 @@ mod foo {
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0759
     }
 }
 
@@ -34,7 +34,7 @@ mod bar {
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0767
     }
 }
 
@@ -51,7 +51,7 @@ mod baz {
     impl Irrelevant for Box<dyn ObjectTrait> {}
 
     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0767
     }
 }
 
@@ -66,8 +66,29 @@ mod bat {
     }
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0767
     }
 }
 
+mod ban {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for dyn ObjectTrait + '_ {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR E0759
+    }
+}
+
+
 fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
index 00f65a2348935..8765591c4a114 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
@@ -18,5 +18,15 @@ LL |         val.use_self()
    |
    = help: consider replacing `'a` with `'static`
 
-error: aborting due to 2 previous errors
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         val.use_self()
+   |         ^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
index 28a599d12bfd1..ba26c2d67dfa8 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -17,7 +17,7 @@ mod foo {
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0759
     }
 }
 
@@ -34,7 +34,7 @@ mod bar {
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0767
     }
 }
 
@@ -51,7 +51,7 @@ mod baz {
     impl Irrelevant for Box<dyn ObjectTrait> {}
 
     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0767
     }
 }
 
@@ -66,8 +66,29 @@ mod bat {
     }
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR cannot infer an appropriate lifetime
+        val.use_self() //~ ERROR E0767
     }
 }
 
+mod ban {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for dyn ObjectTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+        val.use_self() //~ ERROR E0759
+    }
+}
+
+
 fn main() {}
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 8f8fd9dc32402..425159edbcd4a 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
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
@@ -6,78 +6,102 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-note: when using method `use_self` of trait `foo::MyTrait` on `foo::ObjectTrait`, an implicit `'static` requirement is introduced
+note: `foo::ObjectTrait`'s `impl` of `foo::MyTrait` has an implicit `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26
    |
 LL |     impl MyTrait for dyn ObjectTrait {
-   |                          ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- the `'static` requirement is introduced when calling this method
+   |            -------- `'static` requirement is introduced when calling this method
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13
    |
 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
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl`
    |
-note: when using method `use_self` on `bat::ObjectTrait`, an implicit `'static` requirement is introduced
+note: `bat::ObjectTrait`'s inherent `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
    |
 LL |     impl dyn ObjectTrait {
-   |              ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+   |              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- the `'static` requirement is introduced when calling this method
+   |            -------- `'static` requirement is introduced when calling this method
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl dyn ObjectTrait + '_ {
    |                          ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:13
+   |
+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
+   |
+note: `ban::ObjectTrait`'s `impl` of `ban::MyTrait` has an implicit `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26
+   |
+LL |     impl MyTrait for dyn ObjectTrait {
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- `'static` requirement is introduced when calling this method
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {
+   |                                      ^^^^
+help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                                                                    ^^^^
+
+error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13
    |
 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 captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `bar::MyTrait`
    |
-note: when using method `use_self` of trait `bar::MyTrait` on `bar::ObjectTrait`, an implicit `'static` requirement is introduced
+note: `bar::ObjectTrait`'s `impl` of `bar::MyTrait` has an implicit `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
    |
 LL |     impl MyTrait for dyn ObjectTrait {
-   |                          ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- the `'static` requirement is introduced when calling this method
+   |            -------- `'static` requirement is introduced when calling this method
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13
    |
 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 captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `baz::MyTrait`
    |
-note: when using method `use_self` of trait `baz::MyTrait` on `baz::ObjectTrait`, an implicit `'static` requirement is introduced
+note: `baz::ObjectTrait`'s `impl` of `baz::MyTrait` has an implicit `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait> {
-   |                              ^^^^^^^^^^^ this trait object has an implicit `'static` lifetime requirement
+   |                              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- the `'static` requirement is introduced when calling this method
+   |            -------- `'static` requirement is introduced when calling this method
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {
    |                                          ^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
index d3853445dfdfe..94dd826a15cae 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
@@ -16,7 +16,7 @@ fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
 where
     G: Get<T>
 {
-    move || { //~ ERROR cannot infer an appropriate lifetime
+    move || { //~ ERROR `dest`
         *dest = g.get();
     }
 }
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 9ab060328537b..d7051515f1102 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -6,7 +6,7 @@ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/missing-lifetimes-in-signature.rs:19:5
    |
 LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs
index f78edb1c83a4c..d8446e58dbb63 100644
--- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs
+++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs
@@ -27,7 +27,7 @@ impl Bar {
     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
@@ -38,7 +38,7 @@ impl Baz {
     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
@@ -49,7 +49,7 @@ impl Bat {
     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
@@ -60,7 +60,7 @@ impl Ban {
     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
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 1257e9b172cf7..9f30787f07cc6 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
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:30:31
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
@@ -23,7 +23,7 @@ help: to declare that the trait object captures data from argument `self`, you c
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> {
    |                                                        ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:41:31
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
@@ -44,7 +44,7 @@ help: to declare that the trait object captures data from argument `self`, you c
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> + '_ {
    |                                                        ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:52:31
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
@@ -65,7 +65,7 @@ help: to declare that the trait object captures data from argument `self`, you c
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> + 'a {
    |                                                               ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:63:31
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
index d5aa18eb0f4e7..e951adf030f5c 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
@@ -5,7 +5,7 @@
 
 fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
-    Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(items.iter()) //~ ERROR E0759
 }
 
 fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index dda5de431d309..dd804864dab4f 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `items` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/dyn-trait-underscore.rs:8:20
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {

From b795cf1f8b7afefbbf1121a04786068dd3efb17c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Tue, 30 Jun 2020 17:41:15 -0700
Subject: [PATCH 5/8] Use `ty::Instance::resolve` to identify `'static` bound
 source

---
 .../nice_region_error/static_impl_trait.rs    | 221 ++++++++----------
 src/librustc_middle/traits/mod.rs             |   9 +-
 .../traits/structural_impls.rs                |  15 +-
 .../traits/codegen/mod.rs                     |  13 ++
 .../traits/error_reporting/suggestions.rs     |   2 +-
 src/librustc_typeck/check/method/confirm.rs   |  15 +-
 ...dyn-trait-with-implicit-static-bound.fixed |  23 +-
 ...rait-with-implicit-static-bound.nll.stderr |  10 +-
 ...on-dyn-trait-with-implicit-static-bound.rs |  23 +-
 ...yn-trait-with-implicit-static-bound.stderr |  47 ++--
 10 files changed, 196 insertions(+), 182 deletions(-)

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 9fa905cb5abe9..9c2e02968f607 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
@@ -3,18 +3,20 @@
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::ObligationCauseCode;
+use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+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, AssocItem, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor,
+use rustc_hir::{
+    self as hir, GenericBound, ImplItem, Item, ItemKind, Lifetime, LifetimeName, Node, TraitItem,
+    TyKind,
 };
+use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
 use rustc_span::{MultiSpan, Span};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    /// Print the error message for lifetime errors when the return type is a static impl Trait.
+    /// Print the error message for lifetime errors when the return type is a static `impl Trait`,
+    /// `dyn Trait` or if a method call on a trait object introduces a static requirement.
     pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
         debug!("try_report_static_impl_trait(error={:?})", self.error);
         let tcx = self.tcx();
@@ -34,8 +36,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 sub_r,
                 sup_r,
             ) if **sub_r == RegionKind::ReStatic => {
-                // This is for the implicit `'static` requirement coming from `impl dyn Trait {}`.
-                if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
+                // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
+                if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
                     let param = self.find_param_with_region(sup_r, sub_r)?;
                     let lifetime = if sup_r.has_name() {
                         format!("lifetime `{}`", sup_r)
@@ -55,7 +57,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             .map(|s| format!("`{}`", s))
                             .unwrap_or_else(|| "`fn` parameter".to_string()),
                         lifetime,
-                        assoc.ident,
+                        ctxt.assoc_item.ident,
                     );
                     err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
                     err.span_label(
@@ -63,7 +65,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                         &format!(
                             "...is captured and required to live as long as `'static` here \
                              because of an implicit lifetime bound on the {}",
-                            match assoc.container {
+                            match ctxt.assoc_item.container {
                                 AssocItemContainer::TraitContainer(id) =>
                                     format!("`impl` of `{}`", tcx.def_path_str(id)),
                                 AssocItemContainer::ImplContainer(_) =>
@@ -71,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             },
                         ),
                     );
-                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) {
+                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
                         err.emit();
                         return Some(ErrorReported);
                     } else {
@@ -117,25 +119,26 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
         let mut postfix = String::new();
         if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
-            if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
-                if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc)
+            if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
+                if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt)
                     && fn_returns.is_empty()
                 {
                     err.code(rustc_errors::error_code!(E0767));
                     err.set_primary_message(&format!(
                         "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
                          requirement",
-                        param_name, lifetime, assoc.ident,
+                        param_name, lifetime, ctxt.assoc_item.ident,
                     ));
                     postfix = format!(
                         " because of an implicit lifetime on the {}",
-                        match assoc.container {
+                        match ctxt.assoc_item.container {
                             AssocItemContainer::TraitContainer(id) =>
                                 format!("`impl` of `{}`", tcx.def_path_str(id)),
                             AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(),
                         },
                     );
                 }
+                // }
             }
         }
 
@@ -316,128 +319,104 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     }
 
     /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
-    /// `'static` obligation. Find `impl` blocks that are implemented
+    /// `'static` obligation. Suggest relaxing that implicit bound.
     fn find_impl_on_dyn_trait(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         ty: Ty<'_>,
-        assoc: &AssocItem,
+        ctxt: &UnifyReceiverContext<'tcx>,
     ) -> bool {
         let tcx = self.tcx();
         let mut suggested = false;
 
-        // Find the trait object types in the argument.
-        let mut v = TraitObjectVisitor(vec![]);
-        v.visit_ty(ty);
-
-        let container_id = match assoc.container {
-            // When the obligation comes from an `impl Foo for dyn Bar {}`, we
-            // have the `DefId` of the `trait` itself, not the relevant `impl`
-            // block. Because of this, we have to look at all the `trait`s
-            // available, and filter out all that are not of `Foo` (this `def_id`)
-            // and not of `Bar` (the `filter_map` later in this method).
-            AssocItemContainer::TraitContainer(def_id) => def_id,
+        // Find the method being called.
+        let instance = match ty::Instance::resolve(
+            tcx,
+            ctxt.param_env,
+            ctxt.assoc_item.def_id,
+            self.infcx.resolve_vars_if_possible(&ctxt.substs),
+        ) {
+            Ok(Some(instance)) => instance,
+            _ => return false,
+        };
 
-            // When the obligation comes from an `impl dyn Trait {}`, we already
-            // have the `DefId` of the relevant `Item`, so we use it directly.
-            AssocItemContainer::ImplContainer(def_id) => {
-                if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
-                    tcx.hir().get_if_local(def_id)
-                {
-                    for found_did in &v.0 {
-                        let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
-                        hir_v.visit_ty(self_ty);
-                        if let [span] = &hir_v.0[..] {
-                            let mut multi_span: MultiSpan = vec![*span].into();
-                            multi_span.push_span_label(
-                                *span,
-                                "this has an implicit `'static` lifetime requirement".to_string(),
-                            );
-                            multi_span.push_span_label(
-                                assoc.ident.span,
-                                "`'static` requirement is introduced when calling this method"
-                                    .to_string(),
-                            );
-                            err.span_note(
-                                multi_span,
-                                &format!(
-                                    "`{}`'s inherent `impl` has a `'static` requirement",
-                                    tcx.def_path_str(*found_did),
-                                ),
-                            );
-                            err.span_suggestion_verbose(
-                                span.shrink_to_hi(),
-                                "consider relaxing the implicit `'static` requirement",
-                                " + '_".to_string(),
-                                Applicability::MaybeIncorrect,
-                            );
-                            suggested = true;
-                        }
+        // Get the `Ident` of the method being called and the corresponding `impl` (to point at
+        // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
+        let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) {
+            Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => {
+                match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) {
+                    Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => {
+                        (ident, self_ty)
                     }
+                    _ => return false,
                 }
-                return suggested;
             }
-        };
-
-        // Find all the `impl`s in the local scope that can be called on the type parameter. And
-        // retain all that are `impl`s of the trait that originated the `'static` obligation.
-        // This doesn't find `impl dyn Trait { /**/ }`, but that case is handled above.
-        let impl_self_tys = tcx
-            .all_traits(LOCAL_CRATE)
-            .iter()
-            .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
-            .filter_map(|impl_node| {
-                let impl_did = tcx.hir().local_def_id(*impl_node);
-                match tcx.hir().get_if_local(impl_did.to_def_id()) {
-                    Some(Node::Item(Item {
-                        kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), items, .. },
-                        ..
-                    })) if of_trait.trait_def_id() == Some(container_id) => Some((
-                        self_ty,
-                        // Get the ident of the method, in order to use its `Span`.
-                        items
+            Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => {
+                let parent_id = tcx.hir().get_parent_item(*hir_id);
+                match tcx.hir().find(parent_id) {
+                    Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
+                        // The method being called is defined in the `trait`, but the `'static`
+                        // obligation comes from the `impl`. Find that `impl` so that we can point
+                        // at it in the suggestion.
+                        let trait_did = tcx.hir().local_def_id(parent_id).to_def_id();
+                        match tcx.hir().trait_impls(trait_did)
                             .iter()
-                            .filter(|item| item.ident == assoc.ident)
-                            .map(|item| item.ident)
+                            .filter_map(|impl_node| {
+                                let impl_did = tcx.hir().local_def_id(*impl_node);
+                                match tcx.hir().get_if_local(impl_did.to_def_id()) {
+                                    Some(Node::Item(Item {
+                                        kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. },
+                                        ..
+                                    })) if of_trait.trait_def_id() == Some(trait_did) => Some(self_ty),
+                                    _ => None,
+                                }
+                            })
                             .next()
-                            .unwrap_or(assoc.ident),
-                    )),
-                    _ => None,
+                        {
+                            Some(self_ty) => (ident, self_ty),
+                            _ => return false,
+                        }
+                    }
+                    _ => return false,
                 }
-            });
+            }
+            _ => return false,
+        };
 
-        // Given all the `impl`s of the relevant `trait`, look for those that are implemented for
-        // the trait object in the `fn` parameter type.
-        for (self_ty, method) in impl_self_tys {
-            for found_did in &v.0 {
-                let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
-                hir_v.visit_ty(self_ty);
-                if let [span] = &hir_v.0[..] {
-                    let mut multi_span: MultiSpan = vec![*span].into();
-                    multi_span.push_span_label(
-                        *span,
-                        "this has an implicit `'static` lifetime requirement".to_string(),
-                    );
-                    multi_span.push_span_label(
-                        method.span,
-                        "`'static` requirement is introduced when calling this method".to_string(),
-                    );
-                    err.span_note(
-                        multi_span,
-                        &format!(
-                            "`{}`'s `impl` of `{}` has an implicit `'static` requirement",
-                            tcx.def_path_str(*found_did),
-                            tcx.def_path_str(container_id),
-                        ),
-                    );
-                    err.span_suggestion_verbose(
-                        span.shrink_to_hi(),
-                        "consider relaxing the implicit `'static` requirement",
-                        " + '_".to_string(),
-                        Applicability::MaybeIncorrect,
-                    );
-                    suggested = true;
-                }
+        // Find the trait object types in the argument, so we point at *only* the trait object.
+        let mut v = TraitObjectVisitor(vec![]);
+        v.visit_ty(ty);
+        for found_did in &v.0 {
+            let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
+            hir_v.visit_ty(self_ty);
+            for span in &hir_v.0 {
+                let mut multi_span: MultiSpan = vec![*span].into();
+                multi_span.push_span_label(
+                    *span,
+                    "this has an implicit `'static` lifetime requirement".to_string(),
+                );
+                multi_span.push_span_label(
+                    ident.span,
+                    "calling this method introduces the `impl`'s 'static` requirement".to_string(),
+                );
+                err.span_note(
+                    multi_span,
+                    &format!(
+                        "{} has a `'static` requirement",
+                        match ctxt.assoc_item.container {
+                            AssocItemContainer::TraitContainer(id) =>
+                                format!("`impl` of `{}`", tcx.def_path_str(id)),
+                            AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(),
+                        },
+                    ),
+                );
+                err.span_suggestion_verbose(
+                    span.shrink_to_hi(),
+                    "consider relaxing the implicit `'static` requirement",
+                    " + '_".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+                suggested = true;
             }
         }
         suggested
diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs
index c066ea831b298..d2747e5fc659b 100644
--- a/src/librustc_middle/traits/mod.rs
+++ b/src/librustc_middle/traits/mod.rs
@@ -169,6 +169,13 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct UnifyReceiverContext<'tcx> {
+    pub assoc_item: ty::AssocItem,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub substs: SubstsRef<'tcx>,
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from the span.
@@ -300,7 +307,7 @@ pub enum ObligationCauseCode<'tcx> {
     /// Method receiver
     MethodReceiver,
 
-    UnifyReceiver(Rc<ty::AssocItem>),
+    UnifyReceiver(Box<UnifyReceiverContext<'tcx>>),
 
     /// `return` with no expression
     ReturnNoExpression,
diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs
index 61ef0821733e8..18b4371053a89 100644
--- a/src/librustc_middle/traits/structural_impls.rs
+++ b/src/librustc_middle/traits/structural_impls.rs
@@ -213,13 +213,26 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
             super::StartFunctionType => Some(super::StartFunctionType),
             super::IntrinsicType => Some(super::IntrinsicType),
             super::MethodReceiver => Some(super::MethodReceiver),
-            super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())),
+            super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)),
             super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
             super::TrivialBound => Some(super::TrivialBound),
         }
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> {
+    type Lifted = traits::UnifyReceiverContext<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.param_env).and_then(|param_env| {
+            tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext {
+                assoc_item: self.assoc_item,
+                param_env,
+                substs,
+            })
+        })
+    }
+}
+
 impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
     type Lifted = traits::DerivedObligationCause<'tcx>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
diff --git a/src/librustc_trait_selection/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs
index cf575d3eca9c2..dd7ea55cc1043 100644
--- a/src/librustc_trait_selection/traits/codegen/mod.rs
+++ b/src/librustc_trait_selection/traits/codegen/mod.rs
@@ -6,6 +6,7 @@
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::{
     FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
+    Unimplemented,
 };
 use rustc_errors::ErrorReported;
 use rustc_middle::ty::fold::TypeFoldable;
@@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>(
                 );
                 return Err(ErrorReported);
             }
+            Err(Unimplemented) => {
+                // This can trigger when we probe for the source of a `'static` lifetime requirement
+                // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
+                infcx.tcx.sess.delay_span_bug(
+                    rustc_span::DUMMY_SP,
+                    &format!(
+                        "Encountered error `Unimplemented` selecting `{:?}` during codegen",
+                        trait_ref
+                    ),
+                );
+                return Err(ErrorReported);
+            }
             Err(e) => {
                 bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
             }
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index e94b44d879533..0632ce2319aee 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1706,7 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             | ObligationCauseCode::IntrinsicType
             | ObligationCauseCode::MethodReceiver
             | ObligationCauseCode::ReturnNoExpression
-            | ObligationCauseCode::UnifyReceiver(_)
+            | ObligationCauseCode::UnifyReceiver(..)
             | ObligationCauseCode::MiscObligation => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 58cbe8b2479d6..ed84095ae6b0c 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -6,7 +6,7 @@ use crate::hir::def_id::DefId;
 use crate::hir::GenericArg;
 use rustc_hir as hir;
 use rustc_infer::infer::{self, InferOk};
-use rustc_middle::traits::ObligationCauseCode;
+use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
@@ -16,7 +16,6 @@ use rustc_span::Span;
 use rustc_trait_selection::traits;
 
 use std::ops::Deref;
-use std::rc::Rc;
 
 struct ConfirmContext<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -97,7 +96,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
             self_ty, method_sig_rcvr, method_sig, method_predicates
         );
-        self.unify_receivers(self_ty, method_sig_rcvr, &pick);
+        self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs);
 
         let (method_sig, method_predicates) =
             self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
@@ -345,12 +344,20 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         self_ty: Ty<'tcx>,
         method_self_ty: Ty<'tcx>,
         pick: &probe::Pick<'tcx>,
+        substs: SubstsRef<'tcx>,
     ) {
         debug!(
             "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
             self_ty, method_self_ty, self.span, pick
         );
-        let cause = self.cause(self.span, ObligationCauseCode::UnifyReceiver(Rc::new(pick.item)));
+        let cause = self.cause(
+            self.span,
+            ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
+                assoc_item: pick.item,
+                param_env: self.param_env,
+                substs,
+            })),
+        );
         match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
index 832b185e619fa..45e6cfdb82131 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
@@ -5,19 +5,19 @@ mod foo {
     trait OtherTrait<'a> {}
     impl<'a> OtherTrait<'a> for &'a () {}
 
-    trait ObjectTrait {}
-    trait MyTrait {
-        fn use_self(&self) -> &();
+    trait ObjectTrait<T> {}
+    trait MyTrait<T> {
+        fn use_self<K>(&self) -> &();
     }
     trait Irrelevant {}
 
-    impl MyTrait for dyn ObjectTrait + '_ {
-        fn use_self(&self) -> &() { panic!() }
+    impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
+        fn use_self<K>(&self) -> &() { panic!() }
     }
-    impl Irrelevant for dyn ObjectTrait {}
+    impl<T> Irrelevant for dyn ObjectTrait<T> {}
 
-    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR E0759
+    fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+        val.use_self::<T>() //~ ERROR E0759
     }
 }
 
@@ -76,13 +76,11 @@ mod ban {
 
     trait ObjectTrait {}
     trait MyTrait {
-        fn use_self(&self) -> &();
+        fn use_self(&self) -> &() { panic!() }
     }
     trait Irrelevant {}
 
-    impl MyTrait for dyn ObjectTrait + '_ {
-        fn use_self(&self) -> &() { panic!() }
-    }
+    impl MyTrait for dyn ObjectTrait + '_ {}
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
@@ -90,5 +88,4 @@ mod ban {
     }
 }
 
-
 fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
index 8765591c4a114..fb6e62e76da88 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
@@ -1,10 +1,10 @@
 error[E0521]: borrowed data escapes outside of function
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9
    |
-LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-   |                   --- `val` is a reference that is only valid in the function body
-LL |         val.use_self()
-   |         ^^^^^^^^^^^^^^ `val` escapes the function body here
+LL |     fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+   |                      --- `val` is a reference that is only valid in the function body
+LL |         val.use_self::<T>()
+   |         ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here
    |
    = help: consider replacing `'a` with `'static`
 
@@ -19,7 +19,7 @@ LL |         val.use_self()
    = help: consider replacing `'a` with `'static`
 
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:9
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:9
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
    |                   --- `val` is a reference that is only valid in the function body
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
index ba26c2d67dfa8..7de11f4f8fc51 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -5,19 +5,19 @@ mod foo {
     trait OtherTrait<'a> {}
     impl<'a> OtherTrait<'a> for &'a () {}
 
-    trait ObjectTrait {}
-    trait MyTrait {
-        fn use_self(&self) -> &();
+    trait ObjectTrait<T> {}
+    trait MyTrait<T> {
+        fn use_self<K>(&self) -> &();
     }
     trait Irrelevant {}
 
-    impl MyTrait for dyn ObjectTrait {
-        fn use_self(&self) -> &() { panic!() }
+    impl<T> MyTrait<T> for dyn ObjectTrait<T> {
+        fn use_self<K>(&self) -> &() { panic!() }
     }
-    impl Irrelevant for dyn ObjectTrait {}
+    impl<T> Irrelevant for dyn ObjectTrait<T> {}
 
-    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR E0759
+    fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+        val.use_self::<T>() //~ ERROR E0759
     }
 }
 
@@ -76,13 +76,11 @@ mod ban {
 
     trait ObjectTrait {}
     trait MyTrait {
-        fn use_self(&self) -> &();
+        fn use_self(&self) -> &() { panic!() }
     }
     trait Irrelevant {}
 
-    impl MyTrait for dyn ObjectTrait {
-        fn use_self(&self) -> &() { panic!() }
-    }
+    impl MyTrait for dyn ObjectTrait {}
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
@@ -90,5 +88,4 @@ mod ban {
     }
 }
 
-
 fn main() {}
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 425159edbcd4a..1375ac8db8ded 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
@@ -1,22 +1,22 @@
 error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13
    |
-LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-   |                        ------------------- this data with lifetime `'a`...
-LL |         val.use_self()
+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
    |
-note: `foo::ObjectTrait`'s `impl` of `foo::MyTrait` has an implicit `'static` requirement
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26
+note: `impl` of `foo::MyTrait` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32
    |
-LL |     impl MyTrait for dyn ObjectTrait {
-   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
-LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- `'static` requirement is introduced when calling this method
+LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> {
+   |                                ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self<K>(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
 help: consider relaxing the implicit `'static` requirement
    |
-LL |     impl MyTrait for dyn ObjectTrait + '_ {
-   |                                      ^^^^
+LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
+   |                                               ^^^^
 
 error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13
@@ -26,36 +26,37 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + '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`
    |
-note: `bat::ObjectTrait`'s inherent `impl` has a `'static` requirement
+note: inherent `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
    |
 LL |     impl dyn ObjectTrait {
    |              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- `'static` requirement is introduced when calling this method
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl dyn ObjectTrait + '_ {
    |                          ^^^^
 
 error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:13
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:13
    |
 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
    |
-note: `ban::ObjectTrait`'s `impl` of `ban::MyTrait` has an implicit `'static` requirement
+note: `impl` of `ban::MyTrait` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26
    |
-LL |     impl MyTrait for dyn ObjectTrait {
-   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- `'static` requirement is introduced when calling this method
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+...
+LL |     impl MyTrait for dyn ObjectTrait {}
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 help: consider relaxing the implicit `'static` requirement
    |
-LL |     impl MyTrait for dyn ObjectTrait + '_ {
+LL |     impl MyTrait for dyn ObjectTrait + '_ {}
    |                                      ^^^^
 help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound
    |
@@ -70,13 +71,13 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `bar::MyTrait`
    |
-note: `bar::ObjectTrait`'s `impl` of `bar::MyTrait` has an implicit `'static` requirement
+note: `impl` of `bar::MyTrait` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
    |
 LL |     impl MyTrait for dyn ObjectTrait {
    |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- `'static` requirement is introduced when calling this method
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
@@ -90,13 +91,13 @@ LL |     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
 LL |         val.use_self()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `baz::MyTrait`
    |
-note: `baz::ObjectTrait`'s `impl` of `baz::MyTrait` has an implicit `'static` requirement
+note: `impl` of `baz::MyTrait` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait> {
    |                              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- `'static` requirement is introduced when calling this method
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {

From 0c5891b3e7a0764960c2fdc12c67b938fa995945 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 1 Jul 2020 00:24:55 -0700
Subject: [PATCH 6/8] Partially account for case where used method is from
 trait

---
 .../nice_region_error/static_impl_trait.rs    | 26 +++++++++++++++----
 1 file changed, 21 insertions(+), 5 deletions(-)

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 9c2e02968f607..18466b00da971 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
@@ -340,6 +340,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             _ => return false,
         };
 
+        let mut v = TraitObjectVisitor(vec![]);
+        v.visit_ty(ty);
+
         // Get the `Ident` of the method being called and the corresponding `impl` (to point at
         // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
         let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) {
@@ -359,15 +362,30 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                         // obligation comes from the `impl`. Find that `impl` so that we can point
                         // at it in the suggestion.
                         let trait_did = tcx.hir().local_def_id(parent_id).to_def_id();
-                        match tcx.hir().trait_impls(trait_did)
+                        match tcx
+                            .hir()
+                            .trait_impls(trait_did)
                             .iter()
                             .filter_map(|impl_node| {
                                 let impl_did = tcx.hir().local_def_id(*impl_node);
                                 match tcx.hir().get_if_local(impl_did.to_def_id()) {
                                     Some(Node::Item(Item {
-                                        kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. },
+                                        kind: ItemKind::Impl { self_ty, .. },
                                         ..
-                                    })) if of_trait.trait_def_id() == Some(trait_did) => Some(self_ty),
+                                    })) if v.0.iter().all(|did| {
+                                        // FIXME: we should check `self_ty` against the receiver
+                                        // type in the `UnifyReceiver` context, but for now, use
+                                        // this imperfect proxy. This will fail if there are
+                                        // multiple `impl`s for the same trait like
+                                        // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
+                                        // In that case, only the first one will get suggestions.
+                                        let mut hir_v = HirTraitObjectVisitor(vec![], *did);
+                                        hir_v.visit_ty(self_ty);
+                                        !hir_v.0.is_empty()
+                                    }) =>
+                                    {
+                                        Some(self_ty)
+                                    }
                                     _ => None,
                                 }
                             })
@@ -384,8 +402,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         };
 
         // Find the trait object types in the argument, so we point at *only* the trait object.
-        let mut v = TraitObjectVisitor(vec![]);
-        v.visit_ty(ty);
         for found_did in &v.0 {
             let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
             hir_v.visit_ty(self_ty);

From 4344265df9cc1989ff65a8e960266c01a3bc43c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 1 Jul 2020 14:02:57 -0700
Subject: [PATCH 7/8] Handle fully-qualified paths and add test cases

---
 .../nice_region_error/static_impl_trait.rs    | 184 ++++++++++--------
 ...-bound-needing-more-suggestions.nll.stderr |  37 ++++
 ...t-static-bound-needing-more-suggestions.rs | 114 +++++++++++
 ...atic-bound-needing-more-suggestions.stderr |  57 ++++++
 ...dyn-trait-with-implicit-static-bound.fixed |  25 ++-
 ...rait-with-implicit-static-bound.nll.stderr |  14 +-
 ...on-dyn-trait-with-implicit-static-bound.rs |  25 ++-
 ...yn-trait-with-implicit-static-bound.stderr |  46 ++++-
 8 files changed, 404 insertions(+), 98 deletions(-)
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
 create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr

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 18466b00da971..9581ee611fce8 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
@@ -12,6 +12,7 @@ use rustc_hir::{
     TyKind,
 };
 use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
+use rustc_span::symbol::Ident;
 use rustc_span::{MultiSpan, Span};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
@@ -115,33 +116,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
         debug!("try_report_static_impl_trait: param_info={:?}", param);
 
-        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
-
-        let mut postfix = String::new();
-        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
-            if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
-                if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt)
-                    && fn_returns.is_empty()
-                {
-                    err.code(rustc_errors::error_code!(E0767));
-                    err.set_primary_message(&format!(
-                        "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
-                         requirement",
-                        param_name, lifetime, ctxt.assoc_item.ident,
-                    ));
-                    postfix = format!(
-                        " because of an implicit lifetime on the {}",
-                        match ctxt.assoc_item.container {
-                            AssocItemContainer::TraitContainer(id) =>
-                                format!("`impl` of `{}`", tcx.def_path_str(id)),
-                            AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(),
-                        },
-                    );
-                }
-                // }
-            }
-        }
-
         // 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
@@ -168,35 +142,68 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 //    |           ----                               ^
                 err.span_label(
                     sup_origin.span(),
-                    &format!(
-                        "...is captured here, requiring it to live as long as `'static`{}",
-                        postfix
-                    ),
+                    "...is captured here, requiring it to live as long as `'static`",
                 );
             } else {
                 err.span_label(sup_origin.span(), "...is captured here...");
                 if return_sp < sup_origin.span() {
                     err.span_note(
                         return_sp,
-                        &format!("...and is required to live as long as `'static` here{}", postfix),
+                        "...and is required to live as long as `'static` here",
                     );
                 } else {
                     err.span_label(
                         return_sp,
-                        &format!("...and is required to live as long as `'static` here{}", postfix),
+                        "...and is required to live as long as `'static` here",
                     );
                 }
             }
         } else {
             err.span_label(
                 return_sp,
-                &format!(
-                    "...is captured and required to live as long as `'static` here{}",
-                    postfix
-                ),
+                "...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);
+
+        let mut override_error_code = None;
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
+            if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
+                // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
+                // `'static` lifetime when called as a method on a binding: `bar.qux()`.
+                if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
+                    override_error_code = Some(ctxt.assoc_item.ident);
+                }
+            }
+        }
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
+            if let ObligationCauseCode::ItemObligation(item_def_id) = cause.code {
+                // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
+                // lifetime as above, but called using a fully-qualified path to the method:
+                // `Foo::qux(bar)`.
+                let mut v = TraitObjectVisitor(vec![]);
+                v.visit_ty(param.param_ty);
+                if let Some((ident, self_ty)) =
+                    self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0[..])
+                {
+                    if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0[..], ident, self_ty)
+                    {
+                        override_error_code = Some(ident);
+                    }
+                }
+            }
+        }
+        if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
+            // Provide a more targetted error code and description.
+            err.code(rustc_errors::error_code!(E0767));
+            err.set_primary_message(&format!(
+                "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
+                requirement",
+                param_name, lifetime, ident,
+            ));
+        }
+
         debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
         // FIXME: account for the need of parens in `&(dyn Trait + '_)`
         let consider = "consider changing the";
@@ -318,40 +325,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         Some(ErrorReported)
     }
 
-    /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
-    /// `'static` obligation. Suggest relaxing that implicit bound.
-    fn find_impl_on_dyn_trait(
+    fn get_impl_ident_and_self_ty_from_trait(
         &self,
-        err: &mut DiagnosticBuilder<'_>,
-        ty: Ty<'_>,
-        ctxt: &UnifyReceiverContext<'tcx>,
-    ) -> bool {
+        def_id: DefId,
+        trait_objects: &[DefId],
+    ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
         let tcx = self.tcx();
-        let mut suggested = false;
-
-        // Find the method being called.
-        let instance = match ty::Instance::resolve(
-            tcx,
-            ctxt.param_env,
-            ctxt.assoc_item.def_id,
-            self.infcx.resolve_vars_if_possible(&ctxt.substs),
-        ) {
-            Ok(Some(instance)) => instance,
-            _ => return false,
-        };
-
-        let mut v = TraitObjectVisitor(vec![]);
-        v.visit_ty(ty);
-
-        // Get the `Ident` of the method being called and the corresponding `impl` (to point at
-        // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
-        let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) {
+        match tcx.hir().get_if_local(def_id) {
             Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => {
                 match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) {
                     Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => {
-                        (ident, self_ty)
+                        Some((*ident, self_ty))
                     }
-                    _ => return false,
+                    _ => None,
                 }
             }
             Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => {
@@ -372,7 +358,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                                     Some(Node::Item(Item {
                                         kind: ItemKind::Impl { self_ty, .. },
                                         ..
-                                    })) if v.0.iter().all(|did| {
+                                    })) if trait_objects.iter().all(|did| {
                                         // FIXME: we should check `self_ty` against the receiver
                                         // type in the `UnifyReceiver` context, but for now, use
                                         // this imperfect proxy. This will fail if there are
@@ -391,20 +377,64 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             })
                             .next()
                         {
-                            Some(self_ty) => (ident, self_ty),
-                            _ => return false,
+                            Some(self_ty) => Some((*ident, self_ty)),
+                            _ => None,
                         }
                     }
-                    _ => return false,
+                    _ => None,
                 }
             }
+            _ => None,
+        }
+    }
+
+    /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
+    /// `'static` obligation. Suggest relaxing that implicit bound.
+    fn find_impl_on_dyn_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        ty: Ty<'_>,
+        ctxt: &UnifyReceiverContext<'tcx>,
+    ) -> bool {
+        let tcx = self.tcx();
+
+        // Find the method being called.
+        let instance = match ty::Instance::resolve(
+            tcx,
+            ctxt.param_env,
+            ctxt.assoc_item.def_id,
+            self.infcx.resolve_vars_if_possible(&ctxt.substs),
+        ) {
+            Ok(Some(instance)) => instance,
             _ => return false,
         };
 
+        let mut v = TraitObjectVisitor(vec![]);
+        v.visit_ty(ty);
+
+        // Get the `Ident` of the method being called and the corresponding `impl` (to point at
+        // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
+        let (ident, self_ty) =
+            match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0[..]) {
+                Some((ident, self_ty)) => (ident, self_ty),
+                None => return false,
+            };
+
         // Find the trait object types in the argument, so we point at *only* the trait object.
-        for found_did in &v.0 {
+        self.suggest_constrain_dyn_trait_in_impl(err, &v.0[..], ident, self_ty)
+    }
+
+    fn suggest_constrain_dyn_trait_in_impl(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        found_dids: &[DefId],
+        ident: Ident,
+        self_ty: &hir::Ty<'_>,
+    ) -> bool {
+        let mut suggested = false;
+        for found_did in found_dids {
             let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
-            hir_v.visit_ty(self_ty);
+            hir_v.visit_ty(&self_ty);
             for span in &hir_v.0 {
                 let mut multi_span: MultiSpan = vec![*span].into();
                 multi_span.push_span_label(
@@ -415,17 +445,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     ident.span,
                     "calling this method introduces the `impl`'s 'static` requirement".to_string(),
                 );
-                err.span_note(
-                    multi_span,
-                    &format!(
-                        "{} has a `'static` requirement",
-                        match ctxt.assoc_item.container {
-                            AssocItemContainer::TraitContainer(id) =>
-                                format!("`impl` of `{}`", tcx.def_path_str(id)),
-                            AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(),
-                        },
-                    ),
-                );
+                err.span_note(multi_span, "the used `impl` has a `'static` requirement");
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "consider relaxing the implicit `'static` requirement",
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr
new file mode 100644
index 0000000000000..6921926590a69
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr
@@ -0,0 +1,37 @@
+error[E0597]: `val` does not live long enough
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+   |               -- lifetime `'a` defined here                  ------------------- opaque type requires that `val` is borrowed for `'a`
+LL |         val.use_self()
+   |         ^^^ borrowed value does not live long enough
+LL |     }
+   |     - `val` dropped here while still borrowed
+   |
+help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+   |                                                                                  ^^^^
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
new file mode 100644
index 0000000000000..ae6ffa8d93e01
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
@@ -0,0 +1,114 @@
+
+// FIXME: the following cases need to suggest more things to make users reach a working end state.
+
+mod bav {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+        val.use_self() //~ ERROR E0597
+    }
+}
+
+mod bap {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR E0515
+    }
+}
+
+// This case in particular requires the user to write all of the bounds we have in `mod bax`.
+mod bay {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+        val.use_self() //~ ERROR E0767
+    }
+}
+
+mod bax {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait<'a> {
+        fn use_self(&'a self) -> &'a () { panic!() }
+    }
+    trait Bar {}
+
+    impl<'a> MyTrait<'a> for Box<dyn ObjectTrait<Assoc = i32> + 'a> {
+        fn use_self(&'a self) -> &'a () { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+        val.use_self()
+    }
+}
+
+mod baw {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl<'a> MyTrait for Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>>) -> impl OtherTrait<'a> + 'a{
+        val.use_self() //~ ERROR E0515
+    }
+}
+
+fn main() {}
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
new file mode 100644
index 0000000000000..2fab02fd1be45
--- /dev/null
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
@@ -0,0 +1,57 @@
+error[E0597]: `val` does not live long enough
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+   |               -- lifetime `'a` defined here                  ------------------- opaque type requires that `val` is borrowed for `'a`
+LL |         val.use_self()
+   |         ^^^ borrowed value does not live long enough
+LL |     }
+   |     - `val` dropped here while still borrowed
+   |
+help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+   |                                                                                  ^^^^
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:67:13
+   |
+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
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:61:30
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
+   |                                                       ^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
index 45e6cfdb82131..c568738d94b45 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
@@ -78,14 +78,35 @@ mod ban {
     trait MyTrait {
         fn use_self(&self) -> &() { panic!() }
     }
-    trait Irrelevant {}
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
 
     impl MyTrait for dyn ObjectTrait + '_ {}
-    impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
         val.use_self() //~ ERROR E0759
     }
 }
 
+mod bal {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    impl MyTrait for dyn ObjectTrait + '_ {}
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        MyTrait::use_self(val) //~ ERROR E0759
+    }
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
index fb6e62e76da88..697467dc3a630 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
@@ -19,7 +19,7 @@ LL |         val.use_self()
    = help: consider replacing `'a` with `'static`
 
 error[E0521]: borrowed data escapes outside of function
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:9
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
    |                   --- `val` is a reference that is only valid in the function body
@@ -28,5 +28,15 @@ LL |         val.use_self()
    |
    = help: consider replacing `'a` with `'static`
 
-error: aborting due to 3 previous errors
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         MyTrait::use_self(val)
+   |         ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
index 7de11f4f8fc51..8dd1e5d78de09 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -78,14 +78,35 @@ mod ban {
     trait MyTrait {
         fn use_self(&self) -> &() { panic!() }
     }
-    trait Irrelevant {}
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
 
     impl MyTrait for dyn ObjectTrait {}
-    impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
         val.use_self() //~ ERROR E0759
     }
 }
 
+mod bal {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    impl MyTrait for dyn ObjectTrait {}
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        MyTrait::use_self(val) //~ ERROR E0759
+    }
+}
+
 fn main() {}
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 1375ac8db8ded..7e814fc664625 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
@@ -6,7 +6,7 @@ LL |     fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> +
 LL |         val.use_self::<T>()
    |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-note: `impl` of `foo::MyTrait` has a `'static` requirement
+note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32
    |
 LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> {
@@ -26,7 +26,7 @@ LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + '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`
    |
-note: inherent `impl` has a `'static` requirement
+note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
    |
 LL |     impl dyn ObjectTrait {
@@ -39,15 +39,15 @@ LL |     impl dyn ObjectTrait + '_ {
    |                          ^^^^
 
 error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:13
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:13
    |
 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
    |
-note: `impl` of `ban::MyTrait` has a `'static` requirement
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26
    |
 LL |         fn use_self(&self) -> &() { panic!() }
    |            -------- calling this method introduces the `impl`'s 'static` requirement
@@ -63,15 +63,41 @@ help: to declare that the `impl Trait` captures data from argument `val`, you ca
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
    |                                                                    ^^^^
 
+error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:27
+   |
+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...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
+   |
+LL |         MyTrait::use_self(val)
+   |         ^^^^^^^^^^^^^^^^^
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:104:26
+   |
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+...
+LL |     impl MyTrait for dyn ObjectTrait {}
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {}
+   |                                      ^^^^
+
 error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13
    |
 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 because of an implicit lifetime on the `impl` of `bar::MyTrait`
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-note: `impl` of `bar::MyTrait` has a `'static` requirement
+note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
    |
 LL |     impl MyTrait for dyn ObjectTrait {
@@ -89,9 +115,9 @@ error[E0767]: `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 because of an implicit lifetime on the `impl` of `baz::MyTrait`
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
    |
-note: `impl` of `baz::MyTrait` has a `'static` requirement
+note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait> {
@@ -103,6 +129,6 @@ help: consider relaxing the implicit `'static` requirement
 LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {
    |                                          ^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0759`.

From 7b05fb504194652b1d550babfce403fa11454233 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 20 Jul 2020 13:56:50 -0700
Subject: [PATCH 8/8] Change error code number

---
 src/librustc_error_codes/error_codes.rs              |  2 +-
 .../nice_region_error/static_impl_trait.rs           |  4 ++--
 ...implicit-static-bound-needing-more-suggestions.rs |  3 +--
 ...icit-static-bound-needing-more-suggestions.stderr | 12 ++++++------
 ...mpl-on-dyn-trait-with-implicit-static-bound.fixed |  6 +++---
 .../impl-on-dyn-trait-with-implicit-static-bound.rs  |  6 +++---
 ...pl-on-dyn-trait-with-implicit-static-bound.stderr |  6 +++---
 7 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index a5d4adae8dba4..9d16b968286a7 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -632,5 +632,5 @@ E0770: include_str!("./error_codes/E0770.md"),
     E0755, // `#[ffi_pure]` is only allowed on foreign functions
     E0756, // `#[ffi_const]` is only allowed on foreign functions
     E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
-    E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
+    E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
 }
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 9581ee611fce8..4fa6d9d239424 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
@@ -48,7 +48,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     let mut err = struct_span_err!(
                         tcx.sess,
                         cause.span,
-                        E0767,
+                        E0772,
                         "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
                          requirement",
                         param
@@ -196,7 +196,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         }
         if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
             // Provide a more targetted error code and description.
-            err.code(rustc_errors::error_code!(E0767));
+            err.code(rustc_errors::error_code!(E0772));
             err.set_primary_message(&format!(
                 "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
                 requirement",
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
index ae6ffa8d93e01..b2dc16a27e310 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
@@ -1,4 +1,3 @@
-
 // FIXME: the following cases need to suggest more things to make users reach a working end state.
 
 mod bav {
@@ -64,7 +63,7 @@ mod bay {
     impl Bar for i32 {}
 
     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
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 2fab02fd1be45..00971b41c7ce6 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
@@ -1,5 +1,5 @@
 error[E0597]: `val` does not live long enough
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:22:9
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
    |
 LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
    |               -- lifetime `'a` defined here                  ------------------- opaque type requires that `val` is borrowed for `'a`
@@ -14,7 +14,7 @@ LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrai
    |                                                                                  ^^^^
 
 error[E0515]: cannot return value referencing function parameter `val`
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:44:9
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
    |
 LL |         val.use_self()
    |         ---^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |         val.use_self()
    |         `val` is borrowed here
 
 error[E0515]: cannot return value referencing function parameter `val`
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:110:9
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9
    |
 LL |         val.use_self()
    |         ---^^^^^^^^^^^
@@ -31,8 +31,8 @@ LL |         val.use_self()
    |         returns a value referencing data owned by the current function
    |         `val` is borrowed here
 
-error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
-  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:67:13
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:13
    |
 LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
    |                        -------------------------------------- this data with lifetime `'a`...
@@ -40,7 +40,7 @@ LL |         val.use_self()
    |             ^^^^^^^^ ...is captured 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:61:30
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30
    |
 LL |     impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
index c568738d94b45..3c10f85d9423a 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
@@ -34,7 +34,7 @@ mod bar {
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
@@ -51,7 +51,7 @@ mod baz {
     impl Irrelevant for Box<dyn ObjectTrait> {}
 
     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
@@ -66,7 +66,7 @@ mod bat {
     }
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
index 8dd1e5d78de09..88ab03dfc1ef1 100644
--- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
+++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
@@ -34,7 +34,7 @@ mod bar {
     impl Irrelevant for dyn ObjectTrait {}
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
@@ -51,7 +51,7 @@ mod baz {
     impl Irrelevant for Box<dyn ObjectTrait> {}
 
     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
@@ -66,7 +66,7 @@ mod bat {
     }
 
     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
-        val.use_self() //~ ERROR E0767
+        val.use_self() //~ ERROR E0772
     }
 }
 
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 7e814fc664625..2fb6c25fd1702 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
@@ -18,7 +18,7 @@ help: consider relaxing the implicit `'static` requirement
 LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
    |                                               ^^^^
 
-error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
@@ -89,7 +89,7 @@ help: consider relaxing the implicit `'static` requirement
 LL |     impl MyTrait for dyn ObjectTrait + '_ {}
    |                                      ^^^^
 
-error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13
    |
 LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
@@ -109,7 +109,7 @@ help: consider relaxing the implicit `'static` requirement
 LL |     impl MyTrait for dyn ObjectTrait + '_ {
    |                                      ^^^^
 
-error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13
    |
 LL |     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {