diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 149c7dbef22f5..76e87a9e56629 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 0000000000000..7903e9e83cfb3
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-4.rs
@@ -0,0 +1,21 @@
+struct S(Option<(A, B)>);
+
+impl S {
+ 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 = s;
+ //~^ ERROR mismatched types
+ //~| NOTE expected `S`, found `S`
+ //~| NOTE expected due to this
+ //~| NOTE expected struct `S`
+}
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 0000000000000..fac9701e4a11e
--- /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 = s;
+ | --------- ^ expected `S`, found `S`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `S`
+ found struct `S`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.