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

Allow coercing non-capturing closures to function pointers. #32449

Closed
archshift opened this issue Mar 23, 2016 · 4 comments
Closed

Allow coercing non-capturing closures to function pointers. #32449

archshift opened this issue Mar 23, 2016 · 4 comments

Comments

@archshift
Copy link
Contributor

In C++, you are able to pass a non-capturing lambda as a function pointer, as, for example, a function argument:

void foo(void (*foobar)(void)) {
    // impl
}
void bar() {
    foo([]() { /* do something */ });
}

It would be incredibly convenient for rust to be able to do the same:

fn foo(foobar: fn()) {
    // impl
}
fn bar() {
    foo(|| { /* do something */ });
}

A use case would be a static (const) array of function pointers, where dynamic dispatch is not necessary.
Example in current rust (this is a compilable example):

extern {
  static mut b: u32;
  static n: usize;
}

const a: [&'static Fn(); 4] = [
  &|| unsafe { b = 4 },
  &|| unsafe { b = 2 },
  &|| unsafe { b = 3 },
  &|| unsafe { b = 1 },
];

pub fn main() {
  if n < 4 {
    a[n]();
  }
}

This obviously relies upon dynamic dispatch to a level that rust is unable to optimize away. Ideally it would be possible to use a table of fn()s instead of &'static Fn() and rust would be able to coerce the closures into function pointers because nothing needs to be captured.

Another, possibly more widely-applicable scenario is simply being able to pass a closure into a C function that takes a callback.

@abonander
Copy link
Contributor

I like this proposal, but it might fare better for discussion on either https://github.com/rust-lang/rfcs/issues or https://internals.rust-lang.org/.

Issues on this repo are more for directly actionable tasks, like bugfixes and implementation/stabilization of features which have already gone through the RFC process.

@strega-nil
Copy link
Contributor

One thing that Rust has which C++ doesn't is that functions can be defined anywhere:

const A: [fn(); 4] = [
    {fn tmp() { unsafe { b = 4 } } tmp},
    {fn tmp() { unsafe { b = 3 } } tmp},
    {fn tmp() { unsafe { b = 2 } } tmp},
    {fn tmp() { unsafe { b = 1 } } tmp},
];

so perhaps nicer syntax for this?

@abonander
Copy link
Contributor

We do already have the closure syntax, so adding more syntax for anonymous functions is probably not a good idea as that'd just generate more confusion.

We already use inference to determine which Fn*() trait a closure implements, so maybe we could extend that same framework to function pointers without too much difficulty.

@archshift
Copy link
Contributor Author

I've moved this over to rust-lang/rfcs#1555.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants