Skip to content

Confusing error message about mismatched but equal types #80915

Closed
@FabianWolff

Description

@FabianWolff

Consider this code:

fn foo<T> (f: impl Fn (&T) -> ()) {}

fn main () {
    let cl = |c| -> () { c % 2; };
    foo (cl);
}

This produces the following error message:

error[E0308]: mismatched types
 --> r.rs:5:5
  |
5 |     foo (cl);
  |     ^^^ one type is more general than the other
  |
  = note: expected type `FnOnce<(&i32,)>`
             found type `FnOnce<(&i32,)>`

I fail to see the difference between the expected and actual type here. Also, which types is rustc even comparing? Where does the FnOnce come from?

Expected behavior: The code should compile, with the closure argument type being inferred as &i32. In fact, this is what happens as soon as I change the closure definition to

let cl = |c: &_| -> () { c % 2; };

i.e. by adding a hint that c has to be a reference. But this is obvious from foo's signature, isn't it?

At least, there should be a less confusing error message.

Meta

rustc --version --verbose:

rustc 1.49.0 (e1884a8e3 2020-12-29)
binary: rustc
commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
commit-date: 2020-12-29
host: x86_64-unknown-linux-gnu
release: 1.49.0

rustc +nightly --version --verbose:

rustc 1.51.0-nightly (c97f11af7 2021-01-10)
binary: rustc
commit-hash: c97f11af7bc4a6d3578f6a953be04ab2449a5728
commit-date: 2021-01-10
host: x86_64-unknown-linux-gnu
release: 1.51.0-nightly

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions