-
Notifications
You must be signed in to change notification settings - Fork 13k
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 generic foreign functions. #15831
Conversation
cc #10353, in particular this comment:
That being said, I believe times have changed such that an One common use of |
y: T | ||
} | ||
|
||
pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T { s.y } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be used from test.rs
, could you be sure to use it and the struct?
Maybe |
Currently, #[no_mangle] is ignored on generic functions. With this patch, that behavior is preserved so #[no_mangle] works on non-generic externs and is ignored on generic externs. It would be nice to have an error or warning in the cases it's currently ignored, but that's probably a separate issue. I've pushed a new commit that (hopefully) addresses @alexcrichton's comments above, adding a test that non-generic functions (extern and non) can be successfully #[no_mangle]d, and using testcrate::foo in test.rs (it looks like it already was, but without the testcrate:: ...?) |
If it's ignored "properly", it'll at least trigger the unused attribute warning. |
It's ignored improperly in both cases right now. I've filed bug #15844. |
Could you add a test to ensure that this works as expected? #[no_mangle]
extern fn foo<T: Int>(a: T, b: T) -> T { a + b }
fn main() {
assert_eq!(99u8, foo(255u8, 100u8));
assert_eq!(99u16, foo(65535u16, 100u16));
} In an ideal world it would yield a warning that the |
I'll look into the lack of a warning. |
Travis failure looks legit. 14 run-pass tests either crashed the compiler or, interestingly, failed to invoke the linker due to memory exhaustion. |
That actually happens pretty frequently, it's safe to ignore. The travis builders don't necessarily have a lot of umph behind them. |
@alexcrichton If it was just memory, sure. But a bunch of tests actually crashed with SIGILL, which AFAIK is not a known expected failure case of Travis. |
An OOM will result in a SIGILL since it calls the abort intrinsic. |
Without printing anything to stdout? Oh. That's kind of surprising. Also, I was under the impression that allocation failure resulted in task failure, but I don't know where I got that idea from. |
Task failure requires memory allocation. |
I recall us not wanting generic types in extern fns. I'd like to have more light on this issue before merging. |
@brson The only situation it's useful in is passing a callback to a C function. It needs to have the right ABI, but you also want to be able to pass in a (fully instantiated, of course) pointer to a generic function. One workaround that works today is |
I just realized I've got multiple commits here where the earlier ones don't fully implement the feature. What's the policy on that? Do I need to squash them? |
I think it's fine for extern "C" fn's declared in Rust to be generic, but:
|
@nikomatsakis, just to clarify, this is what you're thinking, right? extern foo<T>(t: T) {} // ok
#[no_mangle]
extern foo2<T>(t: T) {} // error
extern {
fn bar<T>(); // error
}
fn main() {
// ok
let _f: extern fn(int) = foo;
let _f: extern fn(i16) = foo;
// ok
fn inner<T>(f: extern fn(T), t: T) { f(t) }
} @rpjohnst it sounds like we'd like to move forward with this, but we're a little hesitant about the amount of testing here. We want to try to think of all the fun ways these can pop up and test them ahead of time to make sure nothing goes awry. |
I reorganized the commits and added a few more tests that should cover all the mentioned cases now. The failed test is run-pass/spawn-stack-too-big, which is entirely unrelated and passes on my machine- is that a Travis failure rather than a test failure? |
It's a Travis issue that all recent PRs have been hitting. |
Thanks @rpjohnst, this looks great! |
Do It looks like I need to skip generics in |
Travis does not execute the run-make tests, but |
Generic extern functions written in Rust have their names mangled, as well as their internal clownshoe __rust_abi functions. This allows e.g. specific monomorphizations of these functions to be used as callbacks. Closes #12502.
It seems |
The logs end with this:
task_abort_no_kill_runtime has a call to Broken bot? |
This allows for things like this: extern "C" fn callback<T>(t: T) { /* ... */ } extern "C" { fn take_callback(c: extern fn(i32)); } and later: take_callback(callback::<i32>); Closes #12502.
fix: Fix docs path for derive macros Fixes rust-lang#15831. Not sure about `attr`, I don't think those are documented anyway. And many macros don't work because we pick the wrong path.
This allows for things like this:
and later:
Closes #12502.