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

Closure seemingly both implements and doesn't implement a trait #79187

Open
alexcrichton opened this issue Nov 18, 2020 · 6 comments
Open

Closure seemingly both implements and doesn't implement a trait #79187

alexcrichton opened this issue Nov 18, 2020 · 6 comments
Labels
A-closures Area: closures (`|args| { .. }`) C-bug Category: This is a bug.

Comments

@alexcrichton
Copy link
Member

This is a bit of an odd issue that I ran into today, and one that I think is a bug in rustc but I'm not 100% certain. Given this code:

trait Foo {}

impl<F> Foo for F where F: Fn(&i32) -> &i32 {}

fn take_foo(_: impl Foo) {}

fn main() {
    // Does not compile
    // take_foo(|a| a);
    // take_foo(|a: &i32| a);
    take_foo(|a: &i32| -> &i32 { a });

    // Does compile
    take_foo(identity(|a| a));
    take_foo(identity(|a: &i32| a));
    take_foo(identity(|a: &i32| -> &i32 { a }));

    fn identity<F>(t: F) -> F
    where
        F: Fn(&i32) -> &i32,
    {
        t
    }
}

this fails to compile with:

error[E0308]: mismatched types
  --> src/main.rs:11:5
   |
11 |     take_foo(|a: &i32| -> &i32 { a });
   |     ^^^^^^^^ one type is more general than the other
   |
   = note: expected reference `&i32`
              found reference `&i32`

error: aborting due to previous error

The perplexing part to me is that both calls to take_foo seem pretty equivalent, but the second compiles while the first does not. I've managed to get a variety of error messages trying to reduce this, the original project had a much more opaque "the trait bound is not satisfied" error. It may be the case though that the fix for the above snippet is the fix for the original snippet too though.

@matthiaskrgr
Copy link
Member

Might be a duplicate of #75791

@apoelstra
Copy link
Contributor

Last night I ran into

fn do_thing<F: FnMut(&usize) -> bool>(mut f: F) -> bool {
    f(&5)
}

fn main() {
    let testfn = |_| true;
    do_thing(testfn);
}

which gives the same error message and may be asimpler case of the same thing.

@alexcrichton
Copy link
Member Author

While perhaps similar to #75791 this one at least isn't a regression, I don't believe this code has ever compiled.

@EliSnow
Copy link

EliSnow commented Nov 19, 2020

Is the underlying issue perhaps what's also causing #71723?

@camelid camelid added A-closures Area: closures (`|args| { .. }`) C-bug Category: This is a bug. labels Nov 20, 2020
@estebank
Copy link
Contributor

CC #79588

@Ekleog
Copy link

Ekleog commented Jan 16, 2021

Workaround that worked for me for something similar: add type annotations to closure arguments and returns until things start to compile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: closures (`|args| { .. }`) C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

7 participants