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

#[derive(...)] for 'extern fn' types #23403

Closed
KyleMayes opened this issue Mar 16, 2015 · 4 comments
Closed

#[derive(...)] for 'extern fn' types #23403

KyleMayes opened this issue Mar 16, 2015 · 4 comments

Comments

@KyleMayes
Copy link
Contributor

When trying to autogenerate Rust bindings from C headers, I came across the problem that I cannot use either #[derive(Clone)] or #[derive(Debug)] with extern fn(...) types.

I would think that the default derivation for extern fn(...) types would be the same as raw pointers. Is there something more complex about extern fn(...) types that prevents them being copied and printed as pointers?

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct FfiStruct {
    pub pointer: *mut i32, // fine
    pub function_pointer: extern fn(), // nope
}

fn main() {
}

Meta

rustc 1.0.0-nightly (3e4be02b8 2015-03-13) (built 2015-03-14)
binary: rustc
commit-hash: 3e4be02b80a3dd27bce20870958fe0aef7e7336d
commit-date: 2015-03-13
build-date: 2015-03-14
host: x86_64-unknown-linux-gnu
release: 1.0.0-nightly
@KyleMayes KyleMayes changed the title #[derive(Clone, Debug)] for 'extern fn' types #[derive(...)] for 'extern fn' types Mar 16, 2015
@nagisa
Copy link
Member

nagisa commented Mar 16, 2015

Note, that fn type in Rust semantically is not a pointer type. It being a pointer is just an implementation detail. This means that copying fn would have to copy the function body and there’s at least two issues here:

  1. You can’t just memcpy (Copy interface demands this to be a case) machine code of the function and expect it to work;
  2. fn bodies are not sized, how would you know how much to memcpy?

Similar reasons for Debug and Clone.

As a solution, you’ll have to implement all these traits manually and implement your desired behaviour yourself.

@KyleMayes
Copy link
Contributor Author

use std::mem;

extern fn test() {
    println!("test()");
}

fn main() {
    println!("{}", mem::size_of::<extern fn()>());

    let a: extern fn() = test;

    let b = a;

    a();
    b();
}

Rust Playpen

It just seems to me that fn and extern fn types already behave like Copy types (I can #[derive(Copy)] on a struct with an extern fn member just fine) so I don't get why they can't derive Clone or Debug too. I can implement them manually (for Debug I can transmute the extern fn to a pointer type and print that) but it would be nice if the compiler could provide these trivial definitions.

@Blei
Copy link
Contributor

Blei commented Apr 5, 2015

This seems plain wrong, now that Copy inherits from Clone:

use std::mem;

type Foo = extern "C" fn() -> i32;

fn main() {
  // Get a pointer from a C library.
  let a: Foo = unsafe { mem::transmute(15usize) };

  let b = a;
  let c = a; // Copy works fine

  let d = a.clone(); // But Clone (which is a prerequisite for Copy) doesn't?
}

Edit: confused inheritance directory.

@Blei
Copy link
Contributor

Blei commented Apr 11, 2015

The clone problem has been solved by #24168. Thanks @kballard!

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

4 participants