about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2021-04-23 18:24:02 -0700
committerEsteban Küber <esteban@kuber.com.ar>2021-04-23 18:57:52 -0700
commitfb1fb7d2ef45760bfe133381286dc750fe51e49e (patch)
treeda4a8c2be1206171a8fbf3f1603d1ad174530c3a
parent64ee9cc28ceda652ac06b7d6bf68d1b7f408cf23 (diff)
downloadrust-fb1fb7d2ef45760bfe133381286dc750fe51e49e.tar.gz
rust-fb1fb7d2ef45760bfe133381286dc750fe51e49e.zip
Tweak suggestion output
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs35
-rw-r--r--src/test/ui/hygiene/trait_items.stderr3
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.stderr8
-rw-r--r--src/test/ui/issues/issue-43189.stderr5
-rw-r--r--src/test/ui/issues/issue-56175.stderr10
-rw-r--r--src/test/ui/rust-2018/trait-import-suggestions.stderr6
-rw-r--r--src/test/ui/shadowed/shadowed-trait-methods.stderr3
-rw-r--r--src/test/ui/suggestions/import-trait-for-method-call.stderr13
-rw-r--r--src/test/ui/traits/item-privacy.stderr3
9 files changed, 67 insertions, 19 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 47e4e1223ff..73e35f0171a 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -988,6 +988,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut alt_rcvr_sugg = false;
         if let SelfSource::MethodCall(rcvr) = source {
             debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
+            let skippable = [
+                self.tcx.lang_items().clone_trait(),
+                self.tcx.lang_items().deref_trait(),
+                self.tcx.lang_items().deref_mut_trait(),
+                self.tcx.lang_items().drop_trait(),
+            ];
             // Try alternative arbitrary self types that could fulfill this call.
             // FIXME: probe for all types that *could* be arbitrary self-types, not
             // just this list.
@@ -996,6 +1002,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
                 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
             ] {
+                if let Ok(pick) = self.lookup_probe(
+                    span,
+                    item_name,
+                    rcvr_ty,
+                    rcvr,
+                    crate::check::method::probe::ProbeScope::AllTraits,
+                ) {
+                    // If the method is defined for the receiver we have, it likely wasn't `use`d.
+                    // We point at the method, but we just skip the rest of the check for arbitrary
+                    // self types and rely on the suggestion to `use` the trait from
+                    // `suggest_valid_traits`.
+                    let did = Some(pick.item.container.id());
+                    let skip = skippable.contains(&did);
+                    if pick.autoderefs == 0 && !skip {
+                        err.span_label(
+                            pick.item.ident.span,
+                            &format!("the method is available for `{}` here", rcvr_ty),
+                        );
+                    }
+                    break;
+                }
                 for (rcvr_ty, pre) in &[
                     (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
                     (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
@@ -1015,13 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // We don't want to suggest a container type when the missing
                             // method is `.clone()` or `.deref()` otherwise we'd suggest
                             // `Arc::new(foo).clone()`, which is far from what the user wants.
-                            let skip = [
-                                self.tcx.lang_items().clone_trait(),
-                                self.tcx.lang_items().deref_trait(),
-                                self.tcx.lang_items().deref_mut_trait(),
-                                self.tcx.lang_items().drop_trait(),
-                            ]
-                            .contains(&did);
+                            let skip = skippable.contains(&did);
                             // Make sure the method is defined for the *actual* receiver: we don't
                             // want to treat `Box<Self>` as a receiver if it only works because of
                             // an autoderef to `&self`
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
index d24336883e9..2913a955dce 100644
--- a/src/test/ui/hygiene/trait_items.stderr
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -1,6 +1,9 @@
 error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/trait_items.rs:17:24
    |
+LL |         fn f(&self) {}
+   |            - the method is available for `()` here
+...
 LL |     fn f() { ::baz::m!(); }
    |              ------------ in this macro invocation
 ...
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index 64ddcb81c0a..b993115502f 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -37,6 +37,9 @@ LL | use no_method_suggested_traits::Reexported;
 error[E0599]: no method named `method` found for type `char` in the current scope
   --> $DIR/no-method-suggested-traits.rs:30:9
    |
+LL |         fn method(&self) {}
+   |            ------ the method is available for `char` here
+...
 LL |     'a'.method();
    |         ^^^^^^ method not found in `char`
    |
@@ -63,6 +66,11 @@ error[E0599]: no method named `method` found for type `i32` in the current scope
    |
 LL |     1i32.method();
    |          ^^^^^^ method not found in `i32`
+   | 
+  ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12
+   |
+LL |         fn method(&self) {}
+   |            ------ the method is available for `i32` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
index 3f63cb8e78f..3a3767c349d 100644
--- a/src/test/ui/issues/issue-43189.stderr
+++ b/src/test/ui/issues/issue-43189.stderr
@@ -3,6 +3,11 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope
    |
 LL |     ().a();
    |        ^ method not found in `()`
+   | 
+  ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
+   |
+LL |     fn a(&self) {}
+   |        - the method is available for `()` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr
index ee3f609f47d..e6b0fffce66 100644
--- a/src/test/ui/issues/issue-56175.stderr
+++ b/src/test/ui/issues/issue-56175.stderr
@@ -3,6 +3,11 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the
    |
 LL |     reexported_trait::FooStruct.trait_method();
    |                                 ^^^^^^^^^^^^ method not found in `FooStruct`
+   | 
+  ::: $DIR/auxiliary/reexported-trait.rs:3:12
+   |
+LL |         fn trait_method(&self) {
+   |            ------------ the method is available for `FooStruct` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
@@ -15,6 +20,11 @@ error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in t
    |
 LL |     reexported_trait::FooStruct.trait_method_b();
    |                                 ^^^^^^^^^^^^^^ method not found in `FooStruct`
+   | 
+  ::: $DIR/auxiliary/reexported-trait.rs:7:12
+   |
+LL |         fn trait_method_b(&self) {
+   |            -------------- the method is available for `FooStruct` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr
index 4b1898345a3..2cf5a073fe5 100644
--- a/src/test/ui/rust-2018/trait-import-suggestions.stderr
+++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr
@@ -1,6 +1,9 @@
 error[E0599]: no method named `foobar` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:22:11
    |
+LL |             fn foobar(&self) { }
+   |                ------ the method is available for `u32` here
+...
 LL |         x.foobar();
    |           ^^^^^^ method not found in `u32`
    |
@@ -11,6 +14,9 @@ LL |         x.foobar();
 error[E0599]: no method named `bar` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:28:7
    |
+LL |         fn bar(&self) { }
+   |            --- the method is available for `u32` here
+...
 LL |     x.bar();
    |       ^^^ method not found in `u32`
    |
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr
index 362907ecbd7..c3b9084affd 100644
--- a/src/test/ui/shadowed/shadowed-trait-methods.stderr
+++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr
@@ -1,6 +1,9 @@
 error[E0599]: no method named `f` found for unit type `()` in the current scope
   --> $DIR/shadowed-trait-methods.rs:13:8
    |
+LL |     pub trait T { fn f(&self) {} }
+   |                      - the method is available for `()` here
+...
 LL |     ().f()
    |        ^ method not found in `()`
    |
diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr
index b6fc09cc5d0..f3ae20552f3 100644
--- a/src/test/ui/suggestions/import-trait-for-method-call.stderr
+++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr
@@ -7,20 +7,9 @@ LL |     h.finish()
   ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
 LL |     fn finish(&self) -> u64;
-   |        ------
-   |        |
-   |        the method is available for `Box<DefaultHasher>` here
-   |        the method is available for `Box<&mut DefaultHasher>` here
+   |        ------ the method is available for `DefaultHasher` here
    |
    = help: items from traits can only be used if the trait is in scope
-help: consider wrapping the receiver expression with the appropriate type
-   |
-LL |     Box::new(h).finish()
-   |     ^^^^^^^^^ ^
-help: consider wrapping the receiver expression with the appropriate type
-   |
-LL |     Box::new(&mut h).finish()
-   |     ^^^^^^^^^^^^^  ^
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL | use std::hash::Hasher;
diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr
index 68d527dc786..30daf8e2770 100644
--- a/src/test/ui/traits/item-privacy.stderr
+++ b/src/test/ui/traits/item-privacy.stderr
@@ -20,6 +20,9 @@ error[E0599]: no method named `b` found for struct `S` in the current scope
 LL | struct S;
    | --------- method `b` not found for this
 ...
+LL |         fn b(&self) { }
+   |            - the method is available for `S` here
+...
 LL |     S.b();
    |       ^ method not found in `S`
    |