Add span to E0271 errors pointing at the "found" associated type bound

b585a74
Opened by chabapok at 2023-01-07 23:16:47

This code produce next error:

fn foo<F, R>(f: F)
    where F: FnOnce() -> R,
          R: IntoItem<Item=()> 
          { }

trait IntoItem {
    type Item;
}

struct S;

impl IntoItem for S {
    type Item = u32;
}

fn main() {    
    foo(|| S);
}

error:

 35 |     foo(|| S);
    |     ^^^ expected u32, found ()
    |
    = note: expected type `u32`
               found type `()`
    = note: required by `foo`

This is not correct, because expected type of foo is () (see functon signature). I'm ask to swap "expected" and "found" notes, because is very confused. For rust beginners this is embarassing (e.g., an error often occurs when works with tokio crate).

It's also incorrect because underlining is on "foo" keyword, but should to argument.

This error might look like this:

35 |     foo(|| S);
   |         ^^^^ expected (), found u32
   |
   = note: expected type `()`
              found type `u32`
   = note: required by `foo`

I suggest making a conclusion about this error easier, such as this:

fn foo(v:u8){ }
fn main(){
    foo(25u16); //expected u8, found u16 <-- this is correct
}
  1. Current output:

    error[E0271]: type mismatch resolving `<S as IntoItem>::Item == ()`
      --> file.rs:17:5
       |
    1  | fn foo<F, R>(f: F)
       |    ---
    2  |     where F: FnOnce() -> R,
    3  |           R: IntoItem<Item=()>
       |                       ------- required by this bound in `foo`
    ...
    17 |     foo(|| S);
       |     ^^^ expected `()`, found `u32`
    

    The swapped types has been resolved, further information is given. As a last tweak, ideally the output could be:

    error[E0271]: type mismatch resolving `<S as IntoItem>::Item == ()`
      --> file.rs:17:5
       |
    1  | fn foo<F, R>(f: F)
       |    ---
    2  |     where F: FnOnce() -> R,
    3  |           R: IntoItem<Item=()>
       |                       ------- required by this bound in `foo`
    ...
    12 | impl IntoItem for S {
       | ------------------- in this `impl`
    13 |     type Item = u32;
       |     --------------- found because of this bound for `S`
    ...
    17 |     foo(|| S);
       |     ^^^ expected `()`, found `u32`
    

    Esteban Kuber at 2020-01-22 19:18:46

  2. The current output:

    error[[E0271]](https://doc.rust-lang.org/nightly/error-index.html#E0271): type mismatch resolving `<S as IntoItem>::Item == ()`
      --> src/main.rs:19:5
       |
    19 |     foo(|| S);
       |     ^^^ type mismatch resolving `<S as IntoItem>::Item == ()`
       |
    note: expected this to be `()`
      --> src/main.rs:15:17
       |
    15 |     type Item = u32;
       |                 ^^^
    note: required by a bound in `foo`
      --> src/main.rs:4:17
       |
    1  | fn foo<F, R>(f: F)
       |    --- required by a bound in this
    ...
    4  |     R: IntoItem<Item = ()>,
       |                 ^^^^^^^^^ required by this bound in `foo`
    

    The only problem here is that we still don't point to the closure argument of foo. This is pretty difficult to do in general, given how the where clause predicates and arguments are related to each other...

    Michael Goulet at 2023-01-07 23:16:47