Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e72c45a

Browse files
Point at which arg causes a binding to be constrained
1 parent 42c4373 commit e72c45a

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259259
hir.body(hir.maybe_body_owned_by(self.body_id).expect("expected item to have body"));
260260
expr_finder.visit_expr(body.value);
261261

262-
let fudge_equals_found_ty = |use_ty: Ty<'tcx>| {
262+
let fudge_ty = |ty: Ty<'tcx>| {
263263
use rustc_infer::infer::type_variable::*;
264264
use rustc_middle::infer::unify_key::*;
265-
let use_ty = use_ty.fold_with(&mut BottomUpFolder {
265+
ty.fold_with(&mut BottomUpFolder {
266266
tcx: self.tcx,
267267
ty_op: |ty| {
268268
if let ty::Infer(infer) = ty.kind() {
@@ -293,7 +293,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
293293
ct
294294
}
295295
},
296-
});
296+
})
297+
};
298+
299+
let fudge_equals_found_ty = |use_ty: Ty<'tcx>| {
300+
let use_ty = fudge_ty(use_ty);
297301
self.can_eq(self.param_env, expected_ty, use_ty)
298302
};
299303

@@ -303,18 +307,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
303307

304308
for window in expr_finder.uses.windows(2) {
305309
let [binding, next_usage] = *window else { continue; };
310+
311+
// Don't go past the binding (always gonna be a nonsense label if so)
312+
if binding.hir_id == expr.hir_id {
313+
break;
314+
}
315+
306316
let Some(next_use_ty) = self.node_ty_opt(next_usage.hir_id) else { continue; };
307-
if !fudge_equals_found_ty(next_use_ty) {
308-
err.span_label(
309-
binding.span,
310-
format!("here the type of `{ident}` is inferred to be `{next_use_ty}`"),
311-
);
312-
return true;
317+
318+
// If the type is not constrained in a way making it not possible to
319+
// equate with `expected_ty` by this point, skip.
320+
if fudge_equals_found_ty(next_use_ty) {
321+
continue;
313322
}
314323

315-
if next_usage.hir_id == expr.hir_id {
316-
break;
324+
if let hir::Node::Expr(parent_expr) = hir.get_parent(binding.hir_id)
325+
&& let hir::ExprKind::MethodCall(segment, rcvr, args, _) = parent_expr.kind
326+
&& rcvr.hir_id == binding.hir_id
327+
{
328+
let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else { continue; };
329+
let rcvr_ty = fudge_ty(rcvr_ty);
330+
if let Ok(method) =
331+
self.lookup_method(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
332+
{
333+
for (expected_arg_ty, arg_expr) in std::iter::zip(&method.sig.inputs()[1..], args) {
334+
let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else { continue; };
335+
let arg_ty = fudge_ty(arg_ty);
336+
let _ = self.try_coerce(arg_expr, arg_ty, *expected_arg_ty, AllowTwoPhase::No, None);
337+
if !self.can_eq(self.param_env, rcvr_ty, expected_ty) {
338+
err.span_label(
339+
arg_expr.span,
340+
format!("this argument has type `{arg_ty}`...")
341+
);
342+
err.span_label(
343+
binding.span,
344+
format!("... which constrains `{ident}` to have type `{next_use_ty}`")
345+
);
346+
return true;
347+
}
348+
}
349+
}
317350
}
351+
352+
err.span_label(
353+
binding.span,
354+
format!("here the type of `{ident}` is inferred to be `{next_use_ty}`"),
355+
);
356+
return true;
318357
}
319358

320359
// We must've not found something that constrained the expr.

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
22
--> $DIR/point-at-inference.rs:12:9
33
|
44
LL | foo.push(i);
5-
| --- here the type of `foo` is inferred to be `Vec<&{integer}>`
5+
| --- - this argument has type `&{integer}`...
6+
| |
7+
| ... which causes `foo` to have type `Vec<&{integer}>`
68
...
79
LL | bar(foo);
810
| --- ^^^ expected `Vec<i32>`, found `Vec<&{integer}>`

tests/ui/typeck/issue-107775.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
22
--> $DIR/issue-107775.rs:35:16
33
|
44
LL | map.insert(1, Struct::do_something);
5-
| --- here the type of `map` is inferred to be `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
5+
| --- -------------------- this argument has type `fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}`...
6+
| |
7+
| ... which causes `map` to have type `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
68
LL | Self { map }
79
| ^^^ expected `HashMap<u16, fn(u8) -> Pin<...>>`, found `HashMap<{integer}, ...>`
810
|

0 commit comments

Comments
 (0)