-
Notifications
You must be signed in to change notification settings - Fork 4
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
Stable Layout and Implementation #11
Comments
Agree, even if Rust allows providing a stable ABI it doesn't automatically mean that libraries have a stable ABI, a stable ABI at that point is more of a guarantee from the library author that the library will maintain ABI compatibility.
Statics will be able to change, as they aren't inlined like constants are and their initialiser will be part of the dynamic library.
A pattern we might see is to have an additional constructor function that returns the value boxed, which will allow using the struct's API across a stable ABI boundary, though at the cost of an allocation. Example: pub struct Foo {
// implementation details which may changes over time
}
impl Foo {
// normal constructor function, still will be able to be used when statically linking with this crate
pub fn new() -> Foo {
...
}
// constructor function which will have a stable ABI
pub fn new_boxed() -> Box<Foo> {
Box::new(Self::new())
}
} |
Such a type can't be dropped on the other side without accidentially using the wrong size to deallocate the memory. |
C++ smart pointers have a custom deleter to facilitate this. Rust may also get away with passing opaque arrays representing the size of the reserved struct, which gives authors some freedom to evolve without having to box. |
Didn't realize that deallocate needed the size of alignment of the pointer 😢. A solution would be to change the return value of Though a proper solution might to have a dynamically sized type pub fn new_boxed() -> Box<extern Foo> {
Box::new(Self::new()) as Box<extern Foo>
} |
Here's some discussion about this topic. I don't get boats' dismissal of the concept - a custom implementation of Box could look like this. This could give as-good-as C++ ergonomics to Rust extern types, while also fitting into Rust's ecosystem of custom smart pointers.
|
a stable ABI involves a lot more than just fixing
#[repr(Rust)]
in place and deciding on a calling convention, but also making sure every struct is ABI compatible and that functions and traits don't change.This work is is the kind of work that I think could be done mostly as a library, with a few compiler changes of course. There's a fundamental trade-off between flexibility and stability here, and Rust chose to lean towards flexibility with regards to ABI.
Functions - inlining affords you no flexibility in changing any externally observable behavior of a function (including bug fixes). Swift has precedent here with
@inlineable
, and we may have to treat everything as#[inline(never)]
unless we have the appropriate#[inline]
.Traits can be thought of as basically a bunch of functions, but with the caveat that associated consts can never change (this is also a problem in Java, C, and C#).
In the same vein, constants and statics can never change their externally visible value, but I assume that this won't be a big deal in practice.
Structs are likely going to be the biggest problem in practice, because the prevalence of privacy and static linking has lead to a behavior of libraries changing their type representations to evolve. Fixing the representation of types has been partially addressed by the Safe Transmute RFC, but it doesn't really address our needs. Some sort of pimpl idiom/extern type is going to be neccessary I might imagine.
A final note about std and libraries is that we'll either have to pin their versions or switch to libraries that promise a stable ABI themselves (if any of their types are used in our ABI). Pinning std is easiest but runs the risk of incompatible desugarings (not to mention lack of cargo-std support). Pinning libraries might lead to annoying issues in practice with DLL hell. I would hate to have shim libraries that pimpl everything, but they may be the price for dynamic linking...
The text was updated successfully, but these errors were encountered: