Skip to content

Commit 5a71029

Browse files
Properly note source of arg mismatch
1 parent 29aee6a commit 5a71029

File tree

5 files changed

+74
-7
lines changed

5 files changed

+74
-7
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+54-3
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6262
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty);
6363

6464
if !suggested {
65-
self.note_source_of_type_mismatch_constraint(err, expr, expected);
65+
self.note_source_of_type_mismatch_constraint(
66+
err,
67+
expr,
68+
TypeMismatchSource::Ty(expected),
69+
);
6670
}
6771
}
6872

@@ -222,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
222226
&self,
223227
err: &mut Diagnostic,
224228
expr: &hir::Expr<'_>,
225-
expected_ty: Ty<'tcx>,
229+
source: TypeMismatchSource<'tcx>,
226230
) -> bool {
227231
let hir = self.tcx.hir();
228232

@@ -295,6 +299,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
295299
},
296300
};
297301

302+
let expected_ty = match source {
303+
TypeMismatchSource::Ty(expected_ty) => expected_ty,
304+
TypeMismatchSource::Arg(call_expr, idx) => {
305+
let hir::ExprKind::MethodCall(segment, _, args, _) = call_expr.kind else {
306+
return false;
307+
};
308+
let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
309+
return false;
310+
};
311+
let possible_rcvr_ty = expr_finder.uses.iter().find_map(|binding| {
312+
let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?;
313+
let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
314+
let method = self
315+
.lookup_method(
316+
possible_rcvr_ty,
317+
segment,
318+
DUMMY_SP,
319+
call_expr,
320+
binding,
321+
args,
322+
)
323+
.ok()?;
324+
let _ = self
325+
.at(&ObligationCause::dummy(), self.param_env)
326+
.eq(DefineOpaqueTypes::No, method.sig.inputs()[idx + 1], arg_ty)
327+
.ok()?;
328+
self.select_obligations_where_possible(|errs| {
329+
// Yeet the errors, we're already reporting errors.
330+
errs.clear();
331+
});
332+
Some(self.resolve_vars_if_possible(possible_rcvr_ty))
333+
});
334+
if let Some(rcvr_ty) = possible_rcvr_ty {
335+
rcvr_ty
336+
} else {
337+
return false;
338+
}
339+
}
340+
};
341+
298342
if !self.can_eq(self.param_env, expected_ty, init_ty.fold_with(&mut fudger)) {
299343
return false;
300344
}
@@ -360,7 +404,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
360404
"... which constrains `{ident}` to have type `{next_use_ty}`"
361405
),
362406
);
363-
if let Ok(ideal_method_sig) = ideal_method_sig {
407+
if matches!(source, TypeMismatchSource::Ty(_))
408+
&& let Ok(ideal_method_sig) = ideal_method_sig
409+
{
364410
self.emit_type_mismatch_suggestions(
365411
err,
366412
arg_expr,
@@ -2044,3 +2090,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20442090
}
20452091
}
20462092
}
2093+
2094+
pub enum TypeMismatchSource<'tcx> {
2095+
Ty(Ty<'tcx>),
2096+
Arg(&'tcx hir::Expr<'tcx>, usize),
2097+
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
472472
err_code: &str,
473473
fn_def_id: Option<DefId>,
474474
call_span: Span,
475-
call_expr: &hir::Expr<'tcx>,
475+
call_expr: &'tcx hir::Expr<'tcx>,
476476
) {
477477
// Next, let's construct the error
478478
let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind {
@@ -808,8 +808,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
808808
format!("arguments to this {} are incorrect", call_name),
809809
);
810810

811-
// TODO: We would like to point out when the rcvr was constrained
812-
// such that the arg mismatch occurs.
811+
if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
812+
&& provided_idx.as_usize() == expected_idx.as_usize()
813+
{
814+
self.note_source_of_type_mismatch_constraint(
815+
&mut err,
816+
rcvr,
817+
crate::demand::TypeMismatchSource::Arg(call_expr, provided_idx.as_usize()),
818+
);
819+
}
813820

814821
// Call out where the function is defined
815822
self.label_fn_like(

tests/ui/type/type-check/point-at-inference-3.fixed

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
fn main() {
33
let mut v = Vec::new();
44
v.push(0i32);
5+
//~^ NOTE this argument has type `i32`...
6+
//~| NOTE ... which causes `v` to have type `Vec<i32>`
57
v.push(0);
68
v.push(1i32); //~ ERROR mismatched types
79
//~^ NOTE expected `i32`, found `u32`

tests/ui/type/type-check/point-at-inference-3.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
fn main() {
33
let mut v = Vec::new();
44
v.push(0i32);
5+
//~^ NOTE this argument has type `i32`...
6+
//~| NOTE ... which causes `v` to have type `Vec<i32>`
57
v.push(0);
68
v.push(1u32); //~ ERROR mismatched types
79
//~^ NOTE expected `i32`, found `u32`

tests/ui/type/type-check/point-at-inference-3.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
error[E0308]: mismatched types
2-
--> $DIR/point-at-inference-3.rs:6:12
2+
--> $DIR/point-at-inference-3.rs:8:12
33
|
4+
LL | v.push(0i32);
5+
| - ---- this argument has type `i32`...
6+
| |
7+
| ... which causes `v` to have type `Vec<i32>`
8+
...
49
LL | v.push(1u32);
510
| ---- ^^^^ expected `i32`, found `u32`
611
| |

0 commit comments

Comments
 (0)