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

#[no_mangle] is silently ignored on generic functions #26753

Closed
jashank opened this issue Jul 3, 2015 · 4 comments
Closed

#[no_mangle] is silently ignored on generic functions #26753

jashank opened this issue Jul 3, 2015 · 4 comments

Comments

@jashank
Copy link
Contributor

jashank commented Jul 3, 2015

A grossly simplified illustrative example.

Assume we're in a library crate (I want to get a shared object out of this so I'm using --crate-type dylib but this appears to be a problem for the general case), and we have the following items defined.

pub enum Action {
    Thing,
    OtherThing,
}

pub trait Game {
    fn legal_action_p(&self, a: &Action) -> bool;
}

If we now wish to expose a function that uses a Game implementor across the library boundary (if, for example, you wish to dlopen(3) then dlsym(3) it), one might expect that they could define a trait bound:

#[no_mangle]
pub extern fn decide_action<T: Game>(g: &T) -> () {
    println!("deciding action!");
    let a = Action::Thing;
    g.legal_action_p(&a);
}

(There's a reason I stuffed a println! in there.)

Compile: rustc testlib.rs --crate-type dylib -g --out-dir target/debug, then:

$ nm target/debug/libtestlib.so | grep -i decide_action
00000000003c5110 D _ZN13decide_action15__STATIC_FMTSTR20h722c5e523a62788eMaaE

Which is, of course, the println! format string. Note a lack of any symbol matching the exact name decide_action.

OK, but if we put the Game impl in a Box:

#[no_mangle]
pub extern fn decide_action(g: &Box<Game>) -> () {
    println!("deciding action!");
    let a = Action::Thing;
    (*g).legal_action_p(&a);
}

Suddenly, it comes back!

$ nm target/debug/libtestlib.so | grep -i decide_action
00000000000ad4b0 T decide_action
00000000000ad4f0 t _ZN13decide_action10__rust_abiE
00000000003c5120 d _ZN13decide_action15__STATIC_FMTSTR20hbe3d66b5baeedebcsbaE

gah!

This presents on stable, beta, and nightly.

This strikes me as a bug, although I'm not sure what in. I suppose you cannot really enforce traits across the extern boundary (although that would be Nice To Have if there's Rust on the other side). On the other hand, how does a box of trait somehow manage to subvert this? I supose this is a compiler error, but I'm a bit fuzzy about what the error is (I guess that if extern fn, then if trait bound, then fail, else do the extern fn).

(As a general note, "FFI" from Rust to Rust, where you explicitly want to plug dylibs, is substantially more uncomfortable than expected.)

@Stebalien
Copy link
Contributor

Rust can't export _generic_ functions (because monomorphization happens at compile time, not link time); this has nothing to do with traits. However, rust probably _shouldn't_ allow generic functions to be marked extern in the first place. As a matter of fact, using a generic extern function _is_ an error:
extern {
    fn decide_action<T: Game>(g: &T);
}
Edit: I'm somewhat incorrect (rust can export monomorphized generic functions (e.g. generic callbacks)). See: https://github.com//pull/15831

/cc @nikomatsakis you cared about this.

@bluss
Copy link
Member

bluss commented Jul 3, 2015

It's not about the trait bound but the type parameter of course. Rustc only instantiates those versions of the function that are actually used. Your workaround -- using &Box<Game> is not generic, has only one version, and so it is compiled in by default.

@arielb1 arielb1 changed the title pub extern fns vanish if a trait bound is present #[no_mangle] is silently ignored on generic functions Jul 4, 2015
@arielb1
Copy link
Contributor

arielb1 commented Jul 4, 2015

#[no_mangle] can't possibly work with generic functions (they can be exported under a gensym-ed name, but that's it). We should make this an error through.

@huonw
Copy link
Member

huonw commented Jul 4, 2015

Dupe of #15844. Thanks for filing!

@huonw huonw closed this as completed Jul 4, 2015
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

5 participants