Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix escaping inference var ICE in point_at_expr_source_of_inferred_type #107175

Merged
merged 2 commits into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 23 additions & 17 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected);
if !suggested {
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span);
}
}

Expand Down Expand Up @@ -222,6 +222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'_>,
found: Ty<'tcx>,
expected: Ty<'tcx>,
mismatch_span: Span,
) -> bool {
let map = self.tcx.hir();

Expand Down Expand Up @@ -270,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lt_op: |_| self.tcx.lifetimes.re_erased,
ct_op: |c| c,
ty_op: |t| match *t.kind() {
ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))),
ty::Infer(ty::TyVar(_)) => self.tcx.mk_ty_var(ty::TyVid::from_u32(0)),
ty::Infer(ty::IntVar(_)) => {
self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
}
Expand All @@ -281,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
};
let mut prev = eraser.fold_ty(ty);
let mut prev_span = None;
let mut prev_span: Option<Span> = None;

for binding in expr_finder.uses {
// In every expression where the binding is referenced, we will look at that
Expand Down Expand Up @@ -333,13 +334,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// inferred in this method call.
let arg = &args[i];
let arg_ty = self.node_ty(arg.hir_id);
err.span_label(
arg.span,
&format!(
"this is of type `{arg_ty}`, which causes `{ident}` to be \
inferred as `{ty}`",
),
);
if !arg.span.overlaps(mismatch_span) {
err.span_label(
arg.span,
&format!(
"this is of type `{arg_ty}`, which causes `{ident}` to be \
inferred as `{ty}`",
),
);
}
param_args.insert(param_ty, (arg, arg_ty));
}
}
Expand Down Expand Up @@ -382,12 +385,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& self.can_eq(self.param_env, ty, found).is_ok()
{
// We only point at the first place where the found type was inferred.
if !segment.ident.span.overlaps(mismatch_span) {
err.span_label(
segment.ident.span,
with_forced_trimmed_paths!(format!(
"here the type of `{ident}` is inferred to be `{ty}`",
)),
);
);}
break;
} else if !param_args.is_empty() {
break;
Expand All @@ -406,12 +410,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We use the *previous* span because if the type is known *here* it means
// it was *evaluated earlier*. We don't do this for method calls because we
// evaluate the method's self type eagerly, but not in any other case.
err.span_label(
span,
with_forced_trimmed_paths!(format!(
"here the type of `{ident}` is inferred to be `{ty}`",
)),
);
if !span.overlaps(mismatch_span) {
err.span_label(
span,
with_forced_trimmed_paths!(format!(
"here the type of `{ident}` is inferred to be `{ty}`",
)),
);
}
break;
}
prev = ty;
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: TypeVariableOriginKind::MiscVariable,
span: full_call_span,
});
self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty);
self.point_at_expr_source_of_inferred_type(
&mut err,
rcvr,
expected,
callee_ty,
provided_arg_span,
);
}
// Call out where the function is defined
self.label_fn_like(
Expand Down
20 changes: 20 additions & 0 deletions tests/ui/typeck/bad-type-in-vec-push.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// The error message here still is pretty confusing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably check how many spans we have and if there's only one, with infer vars in the type, then we skip the customization? Not necessary for this PR.


fn main() {
let mut result = vec![1];
// The type of `result` is constrained to be `Vec<{integer}>` here.
// But the logic we use to find what expression constrains a type
// is not sophisticated enough to know this.

let mut vector = Vec::new();
vector.sort();
result.push(vector);
//~^ ERROR mismatched types
// So it thinks that the type of `result` is constrained here.
}

fn example2() {
let mut x = vec![1];
x.push("");
//~^ ERROR mismatched types
}
29 changes: 29 additions & 0 deletions tests/ui/typeck/bad-type-in-vec-push.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error[E0308]: mismatched types
--> $DIR/bad-type-in-vec-push.rs:11:17
|
LL | vector.sort();
| ------ here the type of `vector` is inferred to be `Vec<_>`
LL | result.push(vector);
| ---- ^^^^^^ expected integer, found struct `Vec`
| |
| arguments to this method are incorrect
|
= note: expected type `{integer}`
found struct `Vec<_>`
note: associated function defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL

error[E0308]: mismatched types
--> $DIR/bad-type-in-vec-push.rs:18:12
|
LL | x.push("");
| ---- ^^ expected integer, found `&str`
| |
| arguments to this method are incorrect
|
note: associated function defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.