mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Rollup merge of #107175 - compiler-errors:bad-types-in-vec-push, r=estebank
Fix escaping inference var ICE in `point_at_expr_source_of_inferred_type` Fixes #107158 `point_at_expr_source_of_inferred_type` uses `lookup_probe` to adjust the self type of a method receiver -- but that method returns inference variables from inside a probe. That means that the ty vars are no longer valid, so we can't use any infcx methods on them. Also, pass some extra span info to hack a quick solution to bad labels, resulting in this diagnostic improvement: ```rust fn example2() { let mut x = vec![1]; x.push(""); } ``` ```diff error[E0308]: mismatched types --> src/main.rs:5:12 | 5 | x.push(""); | ---- ^^ | | | | | expected integer, found `&str` - | | this is of type `&'static str`, which causes `x` to be inferred as `Vec<{integer}>` | arguments to this method are incorrect ``` (since that "which causes `x` to be inferred as `Vec<{integer}>` part is wrong) r? `@estebank` (we really should make this code better in general, cc #106590, but that's a bit bigger issue that needs some more thinking about)
This commit is contained in:
commit
5bc49807dd
@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|| self.suggest_floating_point_literal(err, expr, expected)
|
|| self.suggest_floating_point_literal(err, expr, expected)
|
||||||
|| self.note_result_coercion(err, expr, expected, expr_ty);
|
|| self.note_result_coercion(err, expr, expected, expr_ty);
|
||||||
if !suggested {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expr: &hir::Expr<'_>,
|
expr: &hir::Expr<'_>,
|
||||||
found: Ty<'tcx>,
|
found: Ty<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
|
mismatch_span: Span,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let map = self.tcx.hir();
|
let map = self.tcx.hir();
|
||||||
|
|
||||||
@ -270,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
lt_op: |_| self.tcx.lifetimes.re_erased,
|
lt_op: |_| self.tcx.lifetimes.re_erased,
|
||||||
ct_op: |c| c,
|
ct_op: |c| c,
|
||||||
ty_op: |t| match *t.kind() {
|
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(_)) => {
|
ty::Infer(ty::IntVar(_)) => {
|
||||||
self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
|
self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
|
||||||
}
|
}
|
||||||
@ -281,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut prev = eraser.fold_ty(ty);
|
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 {
|
for binding in expr_finder.uses {
|
||||||
// In every expression where the binding is referenced, we will look at that
|
// In every expression where the binding is referenced, we will look at that
|
||||||
@ -333,13 +334,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// inferred in this method call.
|
// inferred in this method call.
|
||||||
let arg = &args[i];
|
let arg = &args[i];
|
||||||
let arg_ty = self.node_ty(arg.hir_id);
|
let arg_ty = self.node_ty(arg.hir_id);
|
||||||
err.span_label(
|
if !arg.span.overlaps(mismatch_span) {
|
||||||
arg.span,
|
err.span_label(
|
||||||
&format!(
|
arg.span,
|
||||||
"this is of type `{arg_ty}`, which causes `{ident}` to be \
|
&format!(
|
||||||
inferred as `{ty}`",
|
"this is of type `{arg_ty}`, which causes `{ident}` to be \
|
||||||
),
|
inferred as `{ty}`",
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
param_args.insert(param_ty, (arg, arg_ty));
|
param_args.insert(param_ty, (arg, arg_ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,12 +385,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&& self.can_eq(self.param_env, ty, found).is_ok()
|
&& self.can_eq(self.param_env, ty, found).is_ok()
|
||||||
{
|
{
|
||||||
// We only point at the first place where the found type was inferred.
|
// We only point at the first place where the found type was inferred.
|
||||||
|
if !segment.ident.span.overlaps(mismatch_span) {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
segment.ident.span,
|
segment.ident.span,
|
||||||
with_forced_trimmed_paths!(format!(
|
with_forced_trimmed_paths!(format!(
|
||||||
"here the type of `{ident}` is inferred to be `{ty}`",
|
"here the type of `{ident}` is inferred to be `{ty}`",
|
||||||
)),
|
)),
|
||||||
);
|
);}
|
||||||
break;
|
break;
|
||||||
} else if !param_args.is_empty() {
|
} else if !param_args.is_empty() {
|
||||||
break;
|
break;
|
||||||
@ -406,12 +410,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// We use the *previous* span because if the type is known *here* it means
|
// 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
|
// 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.
|
// evaluate the method's self type eagerly, but not in any other case.
|
||||||
err.span_label(
|
if !span.overlaps(mismatch_span) {
|
||||||
span,
|
err.span_label(
|
||||||
with_forced_trimmed_paths!(format!(
|
span,
|
||||||
"here the type of `{ident}` is inferred to be `{ty}`",
|
with_forced_trimmed_paths!(format!(
|
||||||
)),
|
"here the type of `{ident}` is inferred to be `{ty}`",
|
||||||
);
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev = ty;
|
prev = ty;
|
||||||
|
@ -808,7 +808,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
kind: TypeVariableOriginKind::MiscVariable,
|
kind: TypeVariableOriginKind::MiscVariable,
|
||||||
span: full_call_span,
|
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
|
// Call out where the function is defined
|
||||||
self.label_fn_like(
|
self.label_fn_like(
|
||||||
|
20
tests/ui/typeck/bad-type-in-vec-push.rs
Normal file
20
tests/ui/typeck/bad-type-in-vec-push.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// The error message here still is pretty confusing.
|
||||||
|
|
||||||
|
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
tests/ui/typeck/bad-type-in-vec-push.stderr
Normal file
29
tests/ui/typeck/bad-type-in-vec-push.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user