about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs9
-rw-r--r--tests/ui/type/type-check/point-at-inference-4.rs21
-rw-r--r--tests/ui/type/type-check/point-at-inference-4.stderr31
3 files changed, 59 insertions, 2 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 149c7dbef22..76e87a9e566 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -298,6 +298,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // call's arguments and we can provide a more explicit span.
                 let sig = self.tcx.fn_sig(def_id).subst_identity();
                 let def_self_ty = sig.input(0).skip_binder();
+                let param_tys = sig.inputs().skip_binder().iter().skip(1);
+                // If there's an arity mismatch, pointing out the call as the source of an inference
+                // can be misleading, so we skip it.
+                if param_tys.len() != args.len() {
+                    continue;
+                }
                 let rcvr_ty = self.node_ty(rcvr.hir_id);
                 // Get the evaluated type *after* calling the method call, so that the influence
                 // of the arguments can be reflected in the receiver type. The receiver
@@ -323,13 +329,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let mut param_found = FxHashMap::default();
                 if self.can_eq(self.param_env, ty, found) {
                     // We only point at the first place where the found type was inferred.
-                    for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
+                    for (param_ty, arg) in param_tys.zip(args) {
                         if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
                             // We found an argument that references a type parameter in `Self`,
                             // so we assume that this is the argument that caused the found
                             // type, which we know already because of `can_eq` above was first
                             // inferred in this method call.
-                            let arg = &args[i];
                             let arg_ty = self.node_ty(arg.hir_id);
                             if !arg.span.overlaps(mismatch_span) {
                                 err.span_label(
diff --git a/tests/ui/type/type-check/point-at-inference-4.rs b/tests/ui/type/type-check/point-at-inference-4.rs
new file mode 100644
index 00000000000..7903e9e83cf
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-4.rs
@@ -0,0 +1,21 @@
+struct S<A, B>(Option<(A, B)>);
+
+impl<A, B> S<A, B> {
+    fn infer(&self, a: A, b: B) {}
+    //~^ NOTE associated function defined here
+    //~| NOTE
+    //~| NOTE
+}
+
+fn main() {
+    let s = S(None);
+    s.infer(0i32);
+    //~^ ERROR this method takes 2 arguments but 1 argument was supplied
+    //~| NOTE an argument is missing
+    //~| HELP provide the argument
+    let t: S<u32, _> = s;
+    //~^ ERROR mismatched types
+    //~| NOTE expected `S<u32, _>`, found `S<i32, _>`
+    //~| NOTE expected due to this
+    //~| NOTE expected struct `S<u32, _>`
+}
diff --git a/tests/ui/type/type-check/point-at-inference-4.stderr b/tests/ui/type/type-check/point-at-inference-4.stderr
new file mode 100644
index 00000000000..fac9701e4a1
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-4.stderr
@@ -0,0 +1,31 @@
+error[E0061]: this method takes 2 arguments but 1 argument was supplied
+  --> $DIR/point-at-inference-4.rs:12:7
+   |
+LL |     s.infer(0i32);
+   |       ^^^^^------ an argument is missing
+   |
+note: associated function defined here
+  --> $DIR/point-at-inference-4.rs:4:8
+   |
+LL |     fn infer(&self, a: A, b: B) {}
+   |        ^^^^^        ----  ----
+help: provide the argument
+   |
+LL |     s.infer(0i32, /* b */);
+   |            ~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-4.rs:16:24
+   |
+LL |     let t: S<u32, _> = s;
+   |            ---------   ^ expected `S<u32, _>`, found `S<i32, _>`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `S<u32, _>`
+              found struct `S<i32, _>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.