about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-05-27 13:30:16 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-05-27 13:30:16 -0700
commit447d894edf1a7414e52e45f14d17f35012b80aa2 (patch)
tree5ba4926e5541b6a824188d402b9c27bbf3facf5e
parentdcb405667c3b1726ff4c21da1cc93839d183033a (diff)
downloadrust-447d894edf1a7414e52e45f14d17f35012b80aa2.tar.gz
rust-447d894edf1a7414e52e45f14d17f35012b80aa2.zip
Use suggestion for assoc fn called like method
When encountering an unexisting method for a given trait where an
associated function has the same name, suggest using the appropriate
syntax, instead of using `help` text.

When only one candidate is found, do not call it "candidate #1", just
call it "the candidate".
-rw-r--r--src/librustc_typeck/check/method/suggest.rs52
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.stderr2
-rw-r--r--src/test/ui/hygiene/trait_items.stderr2
-rw-r--r--src/test/ui/span/issue-7575.stderr19
4 files changed, 51 insertions, 24 deletions
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 8a575c14787..ce49feed7d9 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -119,11 +119,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             }
                         };
 
-                        let note_str = format!("candidate #{} is defined in an impl{} \
-                                                for the type `{}`",
-                                               idx + 1,
-                                               insertion,
-                                               impl_ty);
+                        let note_str = if sources.len() > 1 {
+                            format!("candidate #{} is defined in an impl{} for the type `{}`",
+                                    idx + 1,
+                                    insertion,
+                                    impl_ty)
+                        } else {
+                            format!("the candidate is defined in an impl{} for the type `{}`",
+                                    insertion,
+                                    impl_ty)
+                        };
                         if let Some(note_span) = note_span {
                             // We have a span pointing to the method. Show note with snippet.
                             err.span_note(self.tcx.sess.codemap().def_span(note_span), &note_str);
@@ -137,11 +142,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             .unwrap();
                         let item_span = self.tcx.sess.codemap()
                             .def_span(self.tcx.def_span(item.def_id));
-                        span_note!(err,
-                                   item_span,
-                                   "candidate #{} is defined in the trait `{}`",
-                                   idx + 1,
-                                   self.tcx.item_path_str(trait_did));
+                        if sources.len() > 1 {
+                            span_note!(err,
+                                       item_span,
+                                       "candidate #{} is defined in the trait `{}`",
+                                       idx + 1,
+                                       self.tcx.item_path_str(trait_did));
+                        } else {
+                            span_note!(err,
+                                       item_span,
+                                       "the candidate is defined in the trait `{}`",
+                                       self.tcx.item_path_str(trait_did));
+                        }
                         err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
                                           instead",
                                           self.tcx.item_path_str(trait_did),
@@ -368,7 +380,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 if !static_sources.is_empty() {
                     err.note("found the following associated functions; to be used as methods, \
                               functions must have a `self` parameter");
-                    err.help(&format!("try with `{}::{}`", self.ty_to_string(actual), item_name));
+                    if let Some(expr) = rcvr_expr {
+                        err.span_suggestion(expr.span.to(span),
+                                            "use associated function syntax intead",
+                                            format!("{}::{}", self.ty_to_string(actual), item_name));
+                    } else {
+                        err.help(&format!("try with `{}::{}`",
+                                          self.ty_to_string(actual), item_name));
+                    }
 
                     report_candidates(&mut err, static_sources);
                 }
@@ -468,9 +487,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         } else {
             let limit = if candidates.len() == 5 { 5 } else { 4 };
             for (i, trait_did) in candidates.iter().take(limit).enumerate() {
-                msg.push_str(&format!("\ncandidate #{}: `use {};`",
-                                        i + 1,
-                                        self.tcx.item_path_str(*trait_did)));
+                if candidates.len() > 1 {
+                    msg.push_str(&format!("\ncandidate #{}: `use {};`",
+                                            i + 1,
+                                            self.tcx.item_path_str(*trait_did)));
+                } else {
+                    msg.push_str(&format!("\n`use {};`",
+                                            self.tcx.item_path_str(*trait_did)));
+                }
             }
             if candidates.len() > limit {
                 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 5753d1a32f7..b3d82e9094b 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -22,7 +22,7 @@ LL |         ().clone() //~ ERROR no method named `clone` found
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
-           candidate #1: `use std::clone::Clone;`
+           `use std::clone::Clone;`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
index 56d9c585d6f..1b2975bcf1c 100644
--- a/src/test/ui/hygiene/trait_items.stderr
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -9,7 +9,7 @@ LL |     pub macro m() { ().f() } //~ ERROR no method named `f` found for type `
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
-           candidate #1: `use foo::T;`
+           `use foo::T;`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index dc2cd4c2ddc..00f08f1d8e0 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -2,10 +2,11 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope
   --> $DIR/issue-7575.rs:74:18
    |
 LL |     u.f8(42) + u.f9(342) + m.fff(42)
-   |                  ^^
+   |                --^^
+   |                |
+   |                help: use associated function syntax intead: `usize::f9`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-   = help: try with `usize::f9`
 note: candidate #1 is defined in the trait `CtxtFn`
   --> $DIR/issue-7575.rs:16:5
    |
@@ -37,11 +38,12 @@ LL | struct Myisize(isize);
    | ---------------------- method `fff` not found for this
 ...
 LL |     u.f8(42) + u.f9(342) + m.fff(42)
-   |                              ^^^
+   |                            --^^^
+   |                            |
+   |                            help: use associated function syntax intead: `Myisize::fff`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-   = help: try with `Myisize::fff`
-note: candidate #1 is defined in an impl for the type `Myisize`
+note: the candidate is defined in an impl for the type `Myisize`
   --> $DIR/issue-7575.rs:51:5
    |
 LL |     fn fff(i: isize) -> isize {
@@ -51,11 +53,12 @@ error[E0599]: no method named `is_str` found for type `T` in the current scope
   --> $DIR/issue-7575.rs:82:7
    |
 LL |     t.is_str()
-   |       ^^^^^^
+   |     --^^^^^^
+   |     |
+   |     help: use associated function syntax intead: `T::is_str`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-   = help: try with `T::is_str`
-note: candidate #1 is defined in the trait `ManyImplTrait`
+note: the candidate is defined in the trait `ManyImplTrait`
   --> $DIR/issue-7575.rs:57:5
    |
 LL |     fn is_str() -> bool {