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

Type errors of the form "expected... but found..." should indicate the source of their expectation #14007

Closed
zwarich opened this issue May 7, 2014 · 7 comments · Fixed by #106400
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-inference Area: Type inference C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@zwarich
Copy link

zwarich commented May 7, 2014

The program

extern crate collections;
use collections::treemap::TreeMap;

fn main() {
    let mut a = TreeMap::new();
    a.insert(0, 1);
    a.insert(0, "foo");
}

gives the type error

treemap-test.rs:7:17: 7:22 error: mismatched types: expected `<generic integer #1>` but found `&'static str` (expected integral variable but found &-ptr)
treemap-test.rs:7     a.insert(0, "foo");
                                   ^~~~~

This error should indicate the source of the expectation that the type parameter is integral.

@ghost ghost self-assigned this Oct 30, 2014
@steveklabnik steveklabnik added A-diagnostics Area: Messages for errors, warnings, and lints I-papercut labels Jan 23, 2015
@steveklabnik
Copy link
Member

Updated code:

use std::collections::BTreeMap;

fn main() {
    let mut a = BTreeMap::new();
    a.insert(0, 1);
    a.insert(0, "foo");
}

Error

 expected `_`,
    found `&'static str`
(expected integral variable,
    found &-ptr) [E0308]
hello.rs:6     a.insert(0, "foo");
                           ^~~~~

It still does not point to insert(0, 1).

@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 21, 2017
@Havvy
Copy link
Contributor

Havvy commented Jun 30, 2018

Triage: No change.

@rylev
Copy link
Member

rylev commented Jul 5, 2021

Triage: the error message has improved but still does not point to the source of the expectation (playground).

error[E0308]: mismatched types
 --> src/main.rs:6:17
  |
6 |     a.insert(0, "foo");
  |                 ^^^^^ expected integer, found `&str`

error: aborting due to previous error

@oli-obk
Copy link
Contributor

oli-obk commented Jul 17, 2021

We could probably add a Map<InferTy, Span> to InferCtxt and look at it whenever we encounter an error during inference. Though we may want to look at something that also works for concrete types, showing us where the type came from for all type mismatch errors.

@eddyb
Copy link
Member

eddyb commented Jul 18, 2021

@oli-obk That effectively already exists, and is called the "origin" of the inference variable, and is already used by diagnostics.
What might be missing is more fine-grained/details "origins" and diagnostic logic to use them.

@eddyb
Copy link
Member

eddyb commented Jul 18, 2021

However, what's really lacking (and for good reasons - i.e. performance), is a "log" of unifications - you may end up with an inference variable, but have no clue as to what else it got unified with, on your way there.

IMO the way to have our cake and eat it too would be to add a generic parameter to InferCtxt and the typeck contexts that use it, that decides whether this is a "fast / inference-only" context, or a "slow / diagnostic-enabled" context - that way, any information used only for diagnostics, doesn't even have to be tracked until an error is observed (and the "fast / inference-only" typeck attempt aborted).

@estebank
Copy link
Contributor

estebank commented Jan 5, 2023

@eddyb you might be interested in looking at the giant hack in #106400, which relies exclusively on the HIR to find the expression where an expected type was inferred.

error[E0308]: mismatched types
    --> src/test/ui/type/type-check/point-at-inference-3.rs:7:12
     |
4    |     v.push(0i32);
     |            ---- this is of type `i32`, which makes `v` to be inferred as `Vec<i32>`
...
7    |     v.push(1u32); //~ ERROR mismatched types
     |       ---- ^^^^ expected `i32`, found `u32`
     |       |
     |       arguments to this function are incorrect
     |
note: associated function defined here
    --> /home/gh-estebank/rust/library/alloc/src/vec/mod.rs:1831:12
     |
1831 |     pub fn push(&mut self, value: T) {
     |            ^^^^
help: change the type of the numeric literal from `u32` to `i32`
     |
7    |     v.push(1i32); //~ ERROR mismatched types
     |             ~~~

For the updated example in the first comment:

error[E0308]: mismatched types
   --> f.rs:6:17
    |
5   |     a.insert(0, 1);
    |              -  - this is of type `{integer}`, which makes `a` to be inferred as `BTreeMap<{integer}, {integer}>`
    |              |
    |              this is of type `{integer}`, which makes `a` to be inferred as `BTreeMap<{integer}, {integer}>`
6   |     a.insert(0, "foo");
    |       ------    ^^^^^ expected integer, found `&str`
    |       |
    |       arguments to this function are incorrect
    |
note: associated function defined here
   --> /home/gh-estebank/rust/library/alloc/src/collections/btree/map.rs:955:12
    |
955 |     pub fn insert(&mut self, key: K, value: V) -> Option<V>
    |            ^^^^^^

compiler-errors added a commit to compiler-errors/rust that referenced this issue Jan 5, 2023
Point at expressions where inference refines an unexpected type

Fix rust-lang#106355. Fix rust-lang#14007. (!)

```
error[E0308]: mismatched types
  --> src/test/ui/type/type-check/point-at-inference.rs:12:9
   |
9  |         foo.push(i);
   |                  - this is of type `&{integer}`, which makes `foo` to be inferred as `Vec<&{integer}>`
...
12 |     bar(foo);
   |     --- ^^^ expected `i32`, found `&{integer}`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected struct `Vec<i32>`
              found struct `Vec<&{integer}>`
note: function defined here
  --> src/test/ui/type/type-check/point-at-inference.rs:2:4
   |
2  | fn bar(_: Vec<i32>) {}
   |    ^^^ -----------
help: consider dereferencing the borrow
   |
9  |         foo.push(*i);
   |                  +
```
@bors bors closed this as completed in 6ae0f08 Jan 6, 2023
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-inference Area: Type inference C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants