about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-07-01 14:02:57 -0700
committerEsteban Küber <esteban@kuber.com.ar>2020-07-22 12:25:55 -0700
commit53d96b5159ee4eb937728bbc33c28c3b98ebebd6 (patch)
tree316f97dce47e66f8a38021faffe36a8fd026e778
parent3712dfc677bb5dff909cdc29fd2da11772ddba9e (diff)
downloadrust-53d96b5159ee4eb937728bbc33c28c3b98ebebd6.tar.gz
rust-53d96b5159ee4eb937728bbc33c28c3b98ebebd6.zip
Handle fully-qualified paths and add test cases
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs184
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr37
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs114
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr57
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed25
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr14
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs25
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr46
8 files changed, 404 insertions, 98 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 18466b00da9..9581ee611fc 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 00000000000..6921926590a
--- /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 00000000000..ae6ffa8d93e
--- /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 00000000000..2fab02fd1be
--- /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 45e6cfdb821..c568738d94b 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 fb6e62e76da..697467dc3a6 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 7de11f4f8fc..8dd1e5d78de 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 1375ac8db8d..7e814fc6646 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`.