From 5497ba1690a1cbf65db8cd1a018bf7fc8b82a73a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Oct 2019 16:11:36 -0700 Subject: [PATCH 1/2] When suggesting assoc function with type params, include turbofish --- src/librustc_typeck/check/method/suggest.rs | 27 +++++++++++++------ .../suggest-assoc-fn-call-with-turbofish.rs | 11 ++++++++ ...uggest-assoc-fn-call-with-turbofish.stderr | 22 +++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 2b34c24b266d0..7ce855c73c7c0 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -462,15 +462,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if static_sources.len() == 1 { 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!("{}::{}", self.ty_to_value_string(actual), item_name), + Applicability::MachineApplicable, + ); } else { - err.help(&format!("try with `{}::{}`", - self.ty_to_string(actual), item_name)); + err.help(&format!( + "try with `{}::{}`", + self.ty_to_value_string(actual), + item_name, + )); } report_candidates(span, &mut err, static_sources); @@ -579,6 +582,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/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 0000000000000..ef4b38de94732 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -0,0 +1,11 @@ +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} +} + +fn main() { + let x = GenericAssocMethod(33i32); + x.default_hello(); + //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod` +} 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 0000000000000..8cfa7de08bb38 --- /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` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 + | +LL | struct GenericAssocMethod(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::::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`. From 3166ce81ec664a0982937050fcedeb3d8538f686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Oct 2019 16:57:14 -0700 Subject: [PATCH 2/2] Account for derefs when suggesting assoc function --- src/librustc_typeck/check/method/suggest.rs | 21 +++++++++++++++++-- src/test/ui/issues/issue-3707.stderr | 2 +- ...oc-fn-call-with-turbofish-through-deref.rs | 13 ++++++++++++ ...n-call-with-turbofish-through-deref.stderr | 19 +++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7ce855c73c7c0..621124541d11d 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -461,17 +461,34 @@ 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_value_string(actual), item_name), + format!("{}::{}", ty_str, item_name), Applicability::MachineApplicable, ); } else { err.help(&format!( "try with `{}::{}`", - self.ty_to_value_string(actual), + ty_str, item_name, )); } diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr index 05c8ce4c3f11e..b98bc572a397c 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 0000000000000..5480adb31015a --- /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 0000000000000..a1c0126146e73 --- /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`.