-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Description
Calls to a C function declared as returning Option<extern fn>
are correctly immediate on 64-bit darwin, but are not immediate on 32-bit linux. I'm assuming the bit width is the issue here, not the platform.
Given that functions are non-nullable, and the only way to declare a nullable function is with Option<extern fn>
, this seems like a rather serious problem. The only way to declare a C function returning a nullable function in the presence of this bug is to declare it as returning an arbitrary raw pointer and wrap it in another function that casts it.
Incidentally, this is not an issue with the null-pointer optimization. size_of()
reports that both extern fn
and Option<extern fn>
are 4
on 32-bit linux, as expected.
Example
Source
foo_c.c:
#include <stdio.h>
typedef void (*voidfunc)(void);
voidfunc foo(int x) {
printf("foo: x=%d\n", x);
return NULL;
}
foo_rust.rs:
use std::libc;
extern {
pub fn foo(x: libc::c_int) -> Option<extern "C" fn()>;
}
fn main() {
unsafe { println!("{:?}", foo(3)); }
}
Makefile:
foo: foo_c.o foo_rust.rs
rustc -o foo --link-args foo_c.o foo_rust.rs
Results
64-bit Darwin:
> ./foo
foo: x=3
None
32-bit Linux:
> ./foo
foo: x=-1220505408
None
Segmentation fault (core dumped)
FWIW, the version of rustc on both platforms is slightly different. The 32-bit Linux platform is using Hans Jørgen Hoel's rust-nightly package, which is almost a day old at 000cda6. 64-bit Darwin is using a newer version of master, at bf30a21. However, I don't see any changes in the newer version that look obviously related.