Comments (1)
Yeah, in this regard safer-ffi
may be a bit ahead of Rust; basically Rust guarantees discriminant elision for things like Option<NonZero…>
, but it doesn't guarantee that yet for things like Option<(NonZero…, usize)>
: technically, a future version of rustc
may choose to lay out the latter as:
struct Option_NonZero_and_usize {
discriminant: Discriminant,
payload: MaybeUninit<(NonZero…, usize)>,
}
enum Discriminant { Some, None }
which indeed wouldn't be FFI-safe.
That being said, in current versions of rustc
, we do have size_of::<Option<(NonZero…, usize)>>() == size_of::<(NonZero…, usize)>()
, which necessarily implies that discriminant elision is happening (this is true for any T
where Option<T>
and T
have the same size). In this instance, it implies that Option<(NonZero…, usize)>
is laid out as (Option<NonZero…>, usize)
.
In our case (c_slice::Ref
& co.), these structures are #[repr(C)]
structures with a single non-nullable field and usize
s for the other fields, and safer-ffi
does check, at compile-time, that they have the same size as their Option
-wrapped versions.
This means that what safer-ffi
does is sound, and that the warning is mostly a false positive:
-
Option<c_slice::Ref…>
does have a well-defined layout (in C, that ofstruct { /* nullable */ Foo_t const * ptr; size_t count; }
); -
but it is true that it is technically possible that a future version of
rustc
would choose a different layout for such a type, which would lead to the compile-time check failing and thus tosafer-ffi
no longer compiling.In practice, this is only a pedantic theoretical concern, since not only there is no reason not to use discriminant elision here, it would also lead generally to major performance regressions across Rust code out there. It's only a matter of time before an RFC guarantees that this elision applies to compound structs with no padding and a single-niched field, hence the practical choice made by
safer-ffi
here.
The development branch of safer-ffi
(the ditto
branch) does thus annotate #[ffi-export]
-ed functions with an #[allow(improper_ctypes)]
to silence this false positive. Feel free to do the same in the meantime.
That being said, if there were to be users of safer-ffi
who find this situation unacceptable, then safer-ffi
could feature-gate this "practical approach" so as to offer a way to opt out of it (to dodge the compile-time-check failing and causing breakage), and cumbersome but correct alternatives; this way users wanting to export a function with, for instance, a optional c_slice::Ref
parameter where the ptr
would be NULL
to express None
would write something like:
#[ffi_export]
fn foo<'a>(
p0: Option<char_p::Ref>,
p1: c_slice::Option::Ref<'a, Foo<'a>>, // Option::Ref would be a special distinct Rust type
) -> i32 {
let p1: Option<c_slice::Ref<'a, Foo<'a>> = p1.into();
}
Aside
Using twice the same named lifetime on a single type is likely to be wrong; I recommend that you write:
#[ffi_export]
fn foo<'a, 'b>(
p0: Option<char_p::Ref<'_>>,
p1: Option<c_slice::<Ref<'a, Foo<'b>>>,
…
for the cases where #[ffi-export]
does not accept full lifetime elision (note it is planned that a future version of #[ffi-export]
will fix the issue with full lifetime elision not being supported 🙂)
from safer_ffi.
Related Issues (20)
- Specifying `[[bin]]` with required features should be a required instruction HOT 1
- Quickstart `crate-type` `lib` seems documented too optional
- Trivial example requires `python-headers` feature to build HOT 2
- No `DOXYGEN` def yields incorrect enum definition HOT 1
- Missing `Clone` impl for `repr_c::Box` (and friends?)
- VS code complains non snake case
- Generated Clone implementation triggers clippy lint about being incorrect for a Copy type HOT 4
- Allow disabling dependency on `inventory v0.1` HOT 2
- Macro ambiguity on nightly: `std::cfg_match` vs `crate::utils::macros::cfg_match` HOT 1
- Conditional proc-macros HOT 2
- How does `safer_ffi` avoid aliasing rule problem? HOT 3
- Compatibility with C++ vector HOT 2
- Handle non-panic Tokio task termination
- no_libc feature?
- C# headers are `public`, when `internal` visibility most likely suffices
- No tag or release for v0.1.5 HOT 1
- Feature Request: Generate rust fn and struct declarations instead of C headers HOT 1
- Python example? HOT 1
- Feature request: serde Serialize and Deserialize support for repr_c::String and repr_c::Vec
- Inconsistent MSRV user guide HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from safer_ffi.