rust icon indicating copy to clipboard operation
rust copied to clipboard

Improve diagnostics like "incompatible types: expected fn item, found a different fn item"

Open jruderman opened this issue 3 years ago • 4 comments

Given the following code (playground):

fn double(n: u32) -> u32 { 
    n * 2
}

fn triple(n: u32) -> u32 {
    n * 3
}

fn f(n: u32) -> u32 {
    let g = if n % 2 == 0 {
        &double
    } else {
        &triple
    };

    g(n)
}

fn main() {
    assert_eq!(f(7), 21);
    assert_eq!(f(8), 16);
}

The current output is:

error[E0308]: `if` and `else` have incompatible types
  --> src/main.rs:13:9
   |
10 |       let g = if n % 2 == 0 {
   |  _____________-
11 | |         &double
   | |         ------- expected because of this
12 | |     } else {
13 | |         &triple
   | |         ^^^^^^^ expected fn item, found a different fn item
14 | |     };
   | |_____- `if` and `else` have incompatible types
   |
   = note: expected reference `&fn(u32) -> u32 {double}`
              found reference `&fn(u32) -> u32 {triple}`

I would like this error to explain why these are incompatible despite having the same signature (or link to an explanation).

I would also like it to suggest an alternative, perhaps one of these:

  • Change &double to &(double as fn(u32) -> u32)
  • Change &double to double

jruderman avatar Oct 03 '22 00:10 jruderman

We should in every E0308 explain that different functions have distinct types, and how to cast them to a fn pointer.

(I thought we were doing that already. :-/ )

estebank avatar Oct 03 '22 17:10 estebank

@estebank we don't do it in this case because these are references to fndef and not just fndef types themselves. We can probably add logic to deeply compare if types are "equal modulo function item types", but it might be kinda complicated.

compiler-errors avatar Oct 03 '22 17:10 compiler-errors

@compiler-errors that makes sense. We might get away with only supporting the simple case of reference to fn like in the OP. For more complex cases we might get over our heads to provide a structured suggestion (but we might want to just check if there are diverging fns and only provide a note for those cases as a hint that might or might not get the user unstuck).

estebank avatar Oct 03 '22 17:10 estebank

@rustbot claim

mattjperez avatar Oct 16 '22 22:10 mattjperez

I've added a help note when there are type mismatched and both expected and found are function items, linking to https://doc.rust-lang.org/reference/types/function-item.html.

I'm still working on how to add the alternative suggestions to the output

Change &double to &(double as fn(u32) -> u32)Change &double to double

But i think adding these to the example in the rust reference page linked above would be helpful either way.

mattjperez avatar Dec 11 '22 08:12 mattjperez