about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-10-08 15:45:29 +0200
committerGitHub <noreply@github.com>2019-10-08 15:45:29 +0200
commit58bfe3b0ec973c27fad86e0d8435c237206834e8 (patch)
tree6e348ad881b7d5acf72ac63a8e7e8ac9838d639a
parent153d3c3ea76ed704bf1b9a4dde1e0d2cb36aaabe (diff)
parent3166ce81ec664a0982937050fcedeb3d8538f686 (diff)
downloadrust-58bfe3b0ec973c27fad86e0d8435c237206834e8.tar.gz
rust-58bfe3b0ec973c27fad86e0d8435c237206834e8.zip
Rollup merge of #65145 - estebank:turbofish-assoc-fn-call, r=varkor
When suggesting assoc function with type params, include turbofish

Fix https://github.com/rust-lang/rust/issues/61412, fix https://github.com/rust-lang/rust/issues/61411.
-rw-r--r--src/librustc_typeck/check/method/suggest.rs44
-rw-r--r--src/test/ui/issues/issue-3707.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs13
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr19
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs11
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr22
6 files changed, 102 insertions, 9 deletions
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 9820ede5b5c..b4b84b61fd6 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -461,16 +461,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_label(span, "this is an associated function, not a method");
                 }
                 if static_sources.len() == 1 {
+                    let ty_str = if let Some(CandidateSource::ImplSource(
+                        impl_did,
+                    )) = static_sources.get(0) {
+                        // When the "method" is resolved through dereferencing, we really want the
+                        // original type that has the associated function for accurate suggestions.
+                        // (#61411)
+                        let ty = self.impl_self_ty(span, *impl_did).ty;
+                        match (&ty.peel_refs().kind, &actual.peel_refs().kind) {
+                            (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
+                                // Use `actual` as it will have more `substs` filled in.
+                                self.ty_to_value_string(actual.peel_refs())
+                            }
+                            _ => self.ty_to_value_string(ty.peel_refs()),
+                        }
+                    } else {
+                        self.ty_to_value_string(actual.peel_refs())
+                    };
                     if let SelfSource::MethodCall(expr) = source {
-                        err.span_suggestion(expr.span.to(span),
-                                            "use associated function syntax instead",
-                                            format!("{}::{}",
-                                                    self.ty_to_string(actual),
-                                                    item_name),
-                                            Applicability::MachineApplicable);
+                        err.span_suggestion(
+                            expr.span.to(span),
+                            "use associated function syntax instead",
+                            format!("{}::{}", ty_str, item_name),
+                            Applicability::MachineApplicable,
+                        );
                     } else {
-                        err.help(&format!("try with `{}::{}`",
-                                          self.ty_to_string(actual), item_name));
+                        err.help(&format!(
+                            "try with `{}::{}`",
+                            ty_str,
+                            item_name,
+                        ));
                     }
 
                     report_candidates(span, &mut err, static_sources);
@@ -586,6 +606,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         None
     }
 
+    /// Print out the type for use in value namespace.
+    fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
+        match ty.kind {
+            ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
+            _ => self.ty_to_string(ty),
+        }
+    }
+
     fn suggest_use_candidates(&self,
                               err: &mut DiagnosticBuilder<'_>,
                               mut msg: String,
diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr
index 05c8ce4c3f1..b98bc572a39 100644
--- a/src/test/ui/issues/issue-3707.stderr
+++ b/src/test/ui/issues/issue-3707.stderr
@@ -5,7 +5,7 @@ LL |         self.boom();
    |         -----^^^^
    |         |    |
    |         |    this is an associated function, not a method
-   |         help: use associated function syntax instead: `&Obj::boom`
+   |         help: use associated function syntax instead: `Obj::boom`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
 note: the candidate is defined in an impl for the type `Obj`
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
new file mode 100644
index 00000000000..5480adb3101
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs
@@ -0,0 +1,13 @@
+use std::cell::RefCell;
+
+struct HasAssocMethod;
+
+impl HasAssocMethod {
+    fn hello() {}
+}
+fn main() {
+    let shared_state = RefCell::new(HasAssocMethod);
+    let state = shared_state.borrow_mut();
+    state.hello();
+    //~^ ERROR no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>`
+}
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
new file mode 100644
index 00000000000..a1c0126146e
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
+   |
+LL |     state.hello();
+   |     ------^^^^^
+   |     |     |
+   |     |     this is an associated function, not a method
+   |     help: use associated function syntax instead: `HasAssocMethod::hello`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `HasAssocMethod`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:6:5
+   |
+LL |     fn hello() {}
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
new file mode 100644
index 00000000000..ef4b38de947
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
@@ -0,0 +1,11 @@
+struct GenericAssocMethod<T>(T);
+
+impl<T> GenericAssocMethod<T> {
+    fn default_hello() {}
+}
+
+fn main() {
+    let x = GenericAssocMethod(33i32);
+    x.default_hello();
+    //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod<i32>`
+}
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
new file mode 100644
index 00000000000..8cfa7de08bb
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
@@ -0,0 +1,22 @@
+error[E0599]: no method named `default_hello` found for type `GenericAssocMethod<i32>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7
+   |
+LL | struct GenericAssocMethod<T>(T);
+   | -------------------------------- method `default_hello` not found for this
+...
+LL |     x.default_hello();
+   |     --^^^^^^^^^^^^^
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<_>`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5
+   |
+LL |     fn default_hello() {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.