about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHirochika Matsumoto <git@hkmatsumoto.com>2022-08-28 17:51:28 +0900
committerHirochika Matsumoto <git@hkmatsumoto.com>2022-08-28 17:51:28 +0900
commit152913767a365d963f2486fb88eff976501d7f72 (patch)
tree20e4158550fdc6f799f95316b909b046639414dc
parent75ed56f0cba4ab95b5d4a67c1f9235a5dbe9df8a (diff)
downloadrust-152913767a365d963f2486fb88eff976501d7f72.tar.gz
rust-152913767a365d963f2486fb88eff976501d7f72.zip
Support method calls
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs53
-rw-r--r--src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr13
-rw-r--r--src/test/ui/suggestions/issue-89064.rs5
-rw-r--r--src/test/ui/suggestions/issue-89064.stderr39
4 files changed, 87 insertions, 23 deletions
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index e4a90329108..36e94c3dce5 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -683,6 +683,14 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
         let num_trait_generics_except_self =
             trait_generics.count() - if trait_generics.has_self { 1 } else { 0 };
 
+        let msg = format!(
+            "consider moving {these} generic argument{s} to the `{name}` trait, which takes up to {num} argument{s}",
+            these = pluralize!("this", num_assoc_fn_excess_args),
+            s = pluralize!(num_assoc_fn_excess_args),
+            name = self.tcx.item_name(trait_),
+            num = num_trait_generics_except_self,
+        );
+
         if let Some(hir_id) = self.path_segment.hir_id
         && let Some(parent_node) = self.tcx.hir().find_parent_node(hir_id)
         && let Some(parent_node) = self.tcx.hir().find(parent_node)
@@ -691,14 +699,22 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 hir::ExprKind::Path(ref qpath) => {
                     self.suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path(
                         err,
-                        trait_,
                         qpath,
+                        msg,
+                        num_assoc_fn_excess_args,
+                        num_trait_generics_except_self
+                    )
+                },
+                hir::ExprKind::MethodCall(..) => {
+                    self.suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
+                        err,
+                        trait_,
+                        expr,
+                        msg,
                         num_assoc_fn_excess_args,
                         num_trait_generics_except_self
                     )
                 },
-                // FIXME(hkmatsumoto): Emit similar suggestion for "x.<assoc fn>()"
-                hir::ExprKind::MethodCall(..) => return,
                 _ => return,
             }
         }
@@ -707,8 +723,8 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
     fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path(
         &self,
         err: &mut Diagnostic,
-        trait_: DefId,
         qpath: &'tcx hir::QPath<'tcx>,
+        msg: String,
         num_assoc_fn_excess_args: usize,
         num_trait_generics_except_self: usize,
     ) {
@@ -719,13 +735,6 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             if num_assoc_fn_excess_args == num_trait_generics_except_self - num_generic_args_supplied_to_trait {
                 if let Some(span) = self.gen_args.span_ext()
                 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    let msg = format!(
-                        "consider moving {these} generic argument{s} to the `{name}` trait, which takes up to {num} argument{s}",
-                        these = pluralize!("this", num_assoc_fn_excess_args),
-                        s = pluralize!(num_assoc_fn_excess_args),
-                        name = self.tcx.item_name(trait_),
-                        num = num_trait_generics_except_self,
-                    );
                     let sugg = vec![
                         (self.path_segment.ident.span, format!("{}::{}", snippet, self.path_segment.ident)),
                         (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned())
@@ -741,6 +750,28 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
         }
     }
 
+    fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
+        &self,
+        err: &mut Diagnostic,
+        trait_: DefId,
+        expr: &'tcx hir::Expr<'tcx>,
+        msg: String,
+        num_assoc_fn_excess_args: usize,
+        num_trait_generics_except_self: usize,
+    ) {
+        if let hir::ExprKind::MethodCall(_, args, _) = expr.kind {
+            assert_eq!(args.len(), 1);
+            if num_assoc_fn_excess_args == num_trait_generics_except_self {
+                if let Some(gen_args) = self.gen_args.span_ext()
+                && let Ok(gen_args) = self.tcx.sess.source_map().span_to_snippet(gen_args)
+                && let Ok(args) = self.tcx.sess.source_map().span_to_snippet(args[0].span) {
+                    let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), args);
+                    err.span_suggestion(expr.span, msg, sugg, Applicability::MaybeIncorrect);
+                }
+            }
+        }
+    }
+
     /// Suggests to remove redundant argument(s):
     ///
     /// ```text
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
index b1b359619dc..d955b4f9651 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -2,15 +2,22 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
   --> $DIR/invalid-const-arg-for-type-param.rs:6:23
    |
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
-   |                       ^^^^^^^^------ help: remove these generics
-   |                       |
-   |                       expected 0 generic arguments
+   |                       ^^^^^^^^ expected 0 generic arguments
    |
 note: associated function defined here, with 0 generic parameters
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
 LL |     fn try_into(self) -> Result<T, Self::Error>;
    |        ^^^^^^^^
+help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument
+   |
+LL |     let _: u32 = TryInto::<32>::try_into(5i32).unwrap();
+   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: remove these generics
+   |
+LL -     let _: u32 = 5i32.try_into::<32>().unwrap();
+LL +     let _: u32 = 5i32.try_into().unwrap();
+   |
 
 error[E0599]: no method named `f` found for struct `S` in the current scope
   --> $DIR/invalid-const-arg-for-type-param.rs:9:7
diff --git a/src/test/ui/suggestions/issue-89064.rs b/src/test/ui/suggestions/issue-89064.rs
index 17a3e8b4cf8..fa5fc899dc0 100644
--- a/src/test/ui/suggestions/issue-89064.rs
+++ b/src/test/ui/suggestions/issue-89064.rs
@@ -27,4 +27,9 @@ fn main() {
     let _ = A::<S>::foo::<S>();
     //~^ ERROR
     //~| HELP remove these generics
+
+    let _ = 42.into::<Option<_>>();
+    //~^ ERROR
+    //~| HELP remove these generics
+    //~| HELP consider moving this generic argument
 }
diff --git a/src/test/ui/suggestions/issue-89064.stderr b/src/test/ui/suggestions/issue-89064.stderr
index 846cd817505..8b2a3881628 100644
--- a/src/test/ui/suggestions/issue-89064.stderr
+++ b/src/test/ui/suggestions/issue-89064.stderr
@@ -9,15 +9,15 @@ note: associated function defined here, with 0 generic parameters
    |
 LL |     fn foo() {}
    |        ^^^
-help: remove these generics
+help: consider moving this generic argument to the `A` trait, which takes up to 1 argument
    |
 LL -     let _ = A::foo::<S>();
-LL +     let _ = A::foo();
+LL +     let _ = A::<S>::foo();
    |
-help: consider moving this generic argument to the `A` trait, which takes up to 1 argument
+help: remove these generics
    |
 LL -     let _ = A::foo::<S>();
-LL +     let _ = A::<S>::foo();
+LL +     let _ = A::foo();
    |
 
 error[E0107]: this associated function takes 0 generic arguments but 2 generic arguments were supplied
@@ -31,15 +31,15 @@ note: associated function defined here, with 0 generic parameters
    |
 LL |     fn bar() {}
    |        ^^^
-help: remove these generics
+help: consider moving these generic arguments to the `B` trait, which takes up to 2 arguments
    |
 LL -     let _ = B::bar::<S, S>();
-LL +     let _ = B::bar();
+LL +     let _ = B::<S, S>::bar();
    |
-help: consider moving these generic arguments to the `B` trait, which takes up to 2 arguments
+help: remove these generics
    |
 LL -     let _ = B::bar::<S, S>();
-LL +     let _ = B::<S, S>::bar();
+LL +     let _ = B::bar();
    |
 
 error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
@@ -56,6 +56,27 @@ note: associated function defined here, with 0 generic parameters
 LL |     fn foo() {}
    |        ^^^
 
-error: aborting due to 3 previous errors
+error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/issue-89064.rs:31:16
+   |
+LL |     let _ = 42.into::<Option<_>>();
+   |                ^^^^ expected 0 generic arguments
+   |
+note: associated function defined here, with 0 generic parameters
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn into(self) -> T;
+   |        ^^^^
+help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument
+   |
+LL |     let _ = Into::<Option<_>>::into(42);
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: remove these generics
+   |
+LL -     let _ = 42.into::<Option<_>>();
+LL +     let _ = 42.into();
+   |
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0107`.