Skip to content

Invalid type inference with Fn and Closures #46742

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

Closed
oberien opened this issue Dec 15, 2017 · 2 comments · Fixed by #71599
Closed

Invalid type inference with Fn and Closures #46742

oberien opened this issue Dec 15, 2017 · 2 comments · Fixed by #71599
Labels
A-closures Area: Closures (`|…| { … }`) 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

@oberien
Copy link
Contributor

oberien commented Dec 15, 2017

The following code compiles just fine:

fn main() {
    let _: i32 = (match "" {
        "+" => ::std::ops::Add::add,
        "-" => ::std::ops::Sub::sub,
        "<" => |a,b| (a < b) as i32,
        _ => unimplemented!(),
    })(5, 5);
}

If we comment out the Sub-line, a compilation error is thrown:

error[E0308]: match arms have incompatible types
 --> src/main.rs:2:18
  |
2 |       let _: i32 = (match "+" {
  |  __________________^
3 | |         "+" => ::std::ops::Add::add,
4 | |         //"-" => ::std::ops::Sub::sub,
5 | |         "<" => |a,b| (a < b) as i32,
6 | |         _ => unimplemented!(),
7 | |     })(5, 5);
  | |______^ expected fn item, found closure
  |
  = note: expected type `fn(_, _) -> <_ as std::ops::Add<_>>::Output {<_ as std::ops::Add<_>>::add}`
             found type `[closure@src/main.rs:5:16: 5:36]`
note: match arm with an incompatible type
 --> src/main.rs:5:16
  |
5 |         "<" => |a,b| (a < b) as i32,
  |                ^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

I previously submitted this issue in #34511 (comment) , but @cramertj pointed out that this is not related to impl Trait. He also modified the example to the above code. Thus, I create this issue to move the discusson away from the impl Trait tracking issue.

/cc @eddyb @nikomatsakis

@eddyb
Copy link
Member

eddyb commented Dec 15, 2017

What happens there is that closures can now be coerced to fn pointers, but not by this code:

// Special-case that coercion alone cannot handle:
// Two function item types of differing IDs or Substs.
if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {

@nikomatsakis ^^ should we also produce function pointers from closures? Maybe at this point we should give up on the TyFnDef vs TyClosure distinction altogether.

@pietroalbini pietroalbini added C-enhancement Category: An issue proposing an enhancement or a PR with one. A-closures Area: Closures (`|…| { … }`) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 30, 2018
@ldm0
Copy link
Contributor

ldm0 commented Apr 27, 2020

Maybe at this point we should give up on the TyFnDef vs TyClosure distinction altogether.

BTW, cc @eddyb Does this make sense today?

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue May 18, 2020
Support coercion between (FnDef | Closure) and (FnDef | Closure)

Fixes rust-lang#46742, fixes rust-lang#48109
Inject `Closure` into the `FnDef x FnDef` coercion special case, which makes coercion of `(FnDef | Closure) x (FnDef | Closure)` possible, where closures should be **non-capturing**.
@bors bors closed this as completed in 58e6447 May 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: Closures (`|…| { … }`) 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.

4 participants