5

What enables a closure type to be used where a function pointer type to be used?

fn takes_ptr(_f: fn(u32) -> u32) {}


fn main() {
    let closure = |n| n;
    takes_ptr(closure)
}

related: there's another question that asks what enables pointer types to be used where closure types are expected: What enables a function trait type to be used where an fn type is expected?

Max Heiber
  • 14,346
  • 12
  • 59
  • 97
  • The answer is covered in The Rust Reference: https://doc.rust-lang.org/reference/types/closure.html#call-traits-and-coercions. "A closure which does not mutate or move out of any captured variables implements `Fn`, indicating that it can be called by shared reference". – Max Heiber Jan 01 '22 at 16:37
  • The "duplicate" question is the opposite of what I asked, can we please re-open? That would make the answers more discoverable. – Max Heiber Jul 04 '22 at 08:47

1 Answers1

5

Closures can be coerced to function pointers if they do not capture any local variables.

Closures that don't capture any variables are effectively the same as normal functions, making this sound. This behaviour was defined in RFC 1558, which says:

A closure that does not move, borrow, or otherwise access (capture) local variables should be coercable to a function pointer (fn).

So |n| n can be coerced since it doesn't capture any local variables, but |n| n + a cannot be coerced since it captures a variable, a, from the outer environment.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
smitop
  • 4,770
  • 2
  • 20
  • 53