Change:
Type inference for the expected type of arguments doesn't work when coercing from a closure expression. For example, this code does not compile (at least, not without an explicit annotation):
Some brief mentoring instructions to fix this: The expected type for closure arguments are deduced using various bits of code in . In particular, the function examines the expected type (which will be in this case). Right now, it only works for trait objects like . It needs to be extended to also check for fn pointers (the variant). Please feel free to ping me on IRC or gitter with questions! (Or ask in #rustc)
I'd like to work on this issue
great! :) Let me know if my instructions suffice, or if you feel you need some more help. I do try to keep up with GH notifications, so you can ask questions here, but you'll definitely get a "snappier" response on IRC or gitter.
OK, so, reading a bit more into that code, I see that it's use of is a bit... icky (I can say that since I wrote it). But I'm just going to go with it. Here is a slightly more detailed account of what needs to be changed: In , when we match a , this variable will be a . This means that it's a function signature, i.e., has the types of arguments and return type. The "Poly" bit means that this function signature may have some higher-ranked regions (e.g., , which is really shorthand for -- the "poly" bit is talking about the ). In fact, if you trace it out, you will see that is really a type alias for , where basically corresponds to the . Now, this function is setup to return a . The "ickiness" I was referring at the beginning with respect to is that, although the first part of this tuple is just , it really should be , because this signature may still refer to bound regions. If you kind of trace it out, you'll see that we wind up adding a binder back on, but in a kind of far-apart part of the code. Sort of a mess, but let's ignore that. So, the meaning of this return: the first part of the tuple is expected fn signature. We basically want to supply the that we extracted from the , more on that in a second. the second part is the "kind" of closure (by value, etc). This is irrelevant here, since it refers specifically to how the closure deals with its environment, and if we are coercing to a fn ptr, we know that there cannot be an environment. We could just return ; we could also yield , since any valid instance will satisfy the trait (which is the most general trait -- a fn that can be called through a shared reference). Therefore, I think we want to return something like .

Discussion:
(sig, kind) } ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), <ins> ty::TyFnPtr(sig) => (Some(sig.skip_binder().clone()), Some(ty::ClosureKind::Fn)), </ins> _ => (None, None), } }

<ins> // Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Ensure that capturing closures are never coerced to fns // Especially interesting as non-capturing closures can be. fn main() { let mut a = 0u8; let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; //~^ ERROR mismatched types } </ins>

<ins> // Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Ensure that capturing closures are never coerced to fns // Especially interesting as non-capturing closures can be. fn main() { let b = 0u8; let bar: fn() -> u8 = || { b }; //~^ ERROR mismatched types } </ins>

<ins> // Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Ensure that capturing closures are never coerced to fns // Especially interesting as non-capturing closures can be. fn main() { let b = 0u8; let baz: fn() -> u8 = (|| { b }) as fn() -> u8; //~^ ERROR non-scalar cast } </ins>

<del> // Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Ensure that capturing closures are never coerced to fns // Especially interesting as non-capturing closures can be. fn main() { let mut a = 0u8; let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; //~^ ERROR mismatched types let b = 0u8; let bar: fn() -> u8 = || { b }; //~^ ERROR mismatched types let baz: fn() -> u8 = || { b } as fn() -> u8; //~^ ERROR mismatched types //~^^ ERROR non-scalar cast } </del>

#![feature(closure_to_fn_coercion)] fn main() { <del> let bar: fn(&mut u32) = |_| {}; //~ ERROR mismatched types //~| expected concrete lifetime, found bound lifetime parameter </del> <ins> let bar: fn(&mut u32) = |_| {}; </ins> fn foo(x: Box<Fn(&i32)>) {} let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;

<ins> // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Ensure that we deduce expected argument types when a `fn()` type is expected (#41755) #![feature(closure_to_fn_coercion)] fn foo(f: fn(Vec<u32>) -> usize) { } fn main() { foo(|x| x.len()) } </ins>