]> git.lizzy.rs Git - rust.git/commitdiff
Add more context to diagnostic
authorEsteban Küber <esteban@kuber.com.ar>
Mon, 29 Jun 2020 01:07:26 +0000 (18:07 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Wed, 22 Jul 2020 19:25:54 +0000 (12:25 -0700)
src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr

index 0aa1d65612ee6bb813e05467fd0ee824b7444353..36d354ea777a4ad816e59ee5c13fb9d4a98f7b4d 100644 (file)
@@ -8,8 +8,10 @@
 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 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
                         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 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
 
         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 @@ fn find_impl_on_dyn_trait(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         ty: Ty<'_>,
-        container: &AssocItemContainer,
+        assoc: &AssocItem,
     ) -> bool {
         let tcx = self.tcx();
         let mut suggested = false;
@@ -272,7 +274,7 @@ fn find_impl_on_dyn_trait(
         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 @@ fn find_impl_on_dyn_trait(
             // 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 @@ fn find_impl_on_dyn_trait(
                 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,
                     );
index 1a03590febe4624fbd3d9c37e95ab7f9d44e866f..8f8fd9dc32402c497a631bebdbb85e8060872200 100644 (file)
@@ -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 + '_> {
    |                                          ^^^^