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

Reformulate point_at_expr_source_of_inferred_type to be more accurate #108687

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
406 changes: 220 additions & 186 deletions compiler/rustc_hir_typeck/src/demand.rs

Large diffs are not rendered by default.

24 changes: 10 additions & 14 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err_code: &str,
fn_def_id: Option<DefId>,
call_span: Span,
call_expr: &hir::Expr<'tcx>,
call_expr: &'tcx hir::Expr<'tcx>,
) {
// Next, let's construct the error
let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind {
Expand Down Expand Up @@ -807,24 +807,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
full_call_span,
format!("arguments to this {} are incorrect", call_name),
);
if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
(callee_ty, &call_expr.kind)

if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
&& provided_idx.as_usize() == expected_idx.as_usize()
{
// Type that would have accepted this argument if it hadn't been inferred earlier.
// FIXME: We leave an inference variable for now, but it'd be nice to get a more
// specific type to increase the accuracy of the diagnostic.
let expected = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: full_call_span,
});
self.point_at_expr_source_of_inferred_type(
self.note_source_of_type_mismatch_constraint(
&mut err,
rcvr,
expected,
callee_ty,
provided_arg_span,
crate::demand::TypeMismatchSource::Arg {
call_expr,
incompatible_arg: provided_idx.as_usize(),
},
);
}

// Call out where the function is defined
self.label_fn_like(
&mut err,
Expand Down
9 changes: 0 additions & 9 deletions tests/ui/type/type-check/assignment-in-if.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ LL | x == 5
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:44:18
|
LL | if y = (Foo { foo: x }) {
| - here the type of `x` is inferred to be `usize`
estebank marked this conversation as resolved.
Show resolved Hide resolved
...
LL | if x == x && x = x && x == x {
| ------ ^ expected `bool`, found `usize`
| |
Expand All @@ -78,9 +75,6 @@ LL | if x == x && x = x && x == x {
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:44:22
|
LL | if y = (Foo { foo: x }) {
| - here the type of `x` is inferred to be `usize`
...
LL | if x == x && x = x && x == x {
| ^ expected `bool`, found `usize`

Expand All @@ -98,9 +92,6 @@ LL | if x == x && x == x && x == x {
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:51:28
|
LL | if y = (Foo { foo: x }) {
| - here the type of `x` is inferred to be `usize`
...
LL | if x == x && x == x && x = x {
| ---------------- ^ expected `bool`, found `usize`
| |
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/type/type-check/point-at-inference-3.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
fn main() {
let mut v = Vec::new();
v.push(0i32);
//~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
//~^ NOTE this argument has type `i32`...
//~| NOTE ... which causes `v` to have type `Vec<i32>`
v.push(0);
v.push(1i32); //~ ERROR mismatched types
//~^ NOTE expected `i32`, found `u32`
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/type/type-check/point-at-inference-3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
fn main() {
let mut v = Vec::new();
v.push(0i32);
//~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
//~^ NOTE this argument has type `i32`...
//~| NOTE ... which causes `v` to have type `Vec<i32>`
v.push(0);
v.push(1u32); //~ ERROR mismatched types
//~^ NOTE expected `i32`, found `u32`
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/type/type-check/point-at-inference-3.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0308]: mismatched types
--> $DIR/point-at-inference-3.rs:7:12
--> $DIR/point-at-inference-3.rs:8:12
|
LL | v.push(0i32);
| ---- this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
| - ---- this argument has type `i32`...
| |
| ... which causes `v` to have type `Vec<i32>`
...
LL | v.push(1u32);
| ---- ^^^^ expected `i32`, found `u32`
Expand Down
3 changes: 3 additions & 0 deletions tests/ui/type/type-check/point-at-inference-4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ fn main() {
let s = S(None);
s.infer(0i32);
//~^ ERROR this method takes 2 arguments but 1 argument was supplied
//~| NOTE this argument has type `i32`...
//~| NOTE ... which causes `s` to have type `S<i32, _>`
//~| NOTE an argument is missing
//~| HELP provide the argument
//~| HELP change the type of the numeric literal from `i32` to `u32`
let t: S<u32, _> = s;
//~^ ERROR mismatched types
//~| NOTE expected `S<u32, _>`, found `S<i32, _>`
Expand Down
11 changes: 10 additions & 1 deletion tests/ui/type/type-check/point-at-inference-4.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,24 @@ LL | s.infer(0i32, /* b */);
| ~~~~~~~~~~~~~~~

error[E0308]: mismatched types
--> $DIR/point-at-inference-4.rs:16:24
--> $DIR/point-at-inference-4.rs:19:24
|
LL | s.infer(0i32);
| - ---- this argument has type `i32`...
| |
| ... which causes `s` to have type `S<i32, _>`
...
LL | let t: S<u32, _> = s;
| --------- ^ expected `S<u32, _>`, found `S<i32, _>`
| |
| expected due to this
|
= note: expected struct `S<u32, _>`
found struct `S<i32, _>`
help: change the type of the numeric literal from `i32` to `u32`
|
LL | s.infer(0u32);
| ~~~

error: aborting due to 2 previous errors

Expand Down
4 changes: 3 additions & 1 deletion tests/ui/type/type-check/point-at-inference.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/point-at-inference.rs:12:9
|
LL | foo.push(i);
| - this is of type `&{integer}`, which causes `foo` to be inferred as `Vec<&{integer}>`
| --- - this argument has type `&{integer}`...
| |
| ... which causes `foo` to have type `Vec<&{integer}>`
...
LL | bar(foo);
| --- ^^^ expected `Vec<i32>`, found `Vec<&{integer}>`
Expand Down
1 change: 0 additions & 1 deletion tests/ui/typeck/bad-type-in-vec-contains.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ LL | primes.contains(3);
| | expected `&_`, found integer
| | help: consider borrowing here: `&3`
| arguments to this method are incorrect
| here the type of `primes` is inferred to be `[_]`
|
= note: expected reference `&_`
found type `{integer}`
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/typeck/bad-type-in-vec-push.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
error[E0308]: mismatched types
--> $DIR/bad-type-in-vec-push.rs:11:17
|
LL | vector.sort();
estebank marked this conversation as resolved.
Show resolved Hide resolved
| ------ here the type of `vector` is inferred to be `Vec<_>`
LL | result.push(vector);
| ---- ^^^^^^ expected integer, found `Vec<_>`
| |
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/typeck/issue-107775.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ error[E0308]: mismatched types
--> $DIR/issue-107775.rs:35:16
|
LL | map.insert(1, Struct::do_something);
| - -------------------- this is of type `fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}`, which causes `map` to be inferred as `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
estebank marked this conversation as resolved.
Show resolved Hide resolved
| |
| this is of type `{integer}`, which causes `map` to be inferred as `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
| --- -------------------- this argument has type `fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}`...
| |
| ... which causes `map` to have type `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
LL | Self { map }
| ^^^ expected `HashMap<u16, fn(u8) -> Pin<...>>`, found `HashMap<{integer}, ...>`
|
Expand Down