-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
extern "C"
functions returning ZSTs
#115091
Comments
note that questions like these will see more activity if asked on https://internals.rust-lang.org/ on zulip |
But something worth pointing out is that something being a ZST is not necessarily part of its public API, so using ZSTs with private fields from other crates in return position is not okay because they could be changed to not be ZSTs in the future. |
Some types may be optimized to ZSTs ; pub enum Errno {
Generic
}
pub extern "C" fn mainloop() -> Result<!, Errno> {
Err(Errno::Generic)
} so the generated glue will be void mainloop(); which is kinda not good. I think for FFI, users should use a type alias: type IfThisReturnsItHasErrored = (); As the type's meaning shouldn't be dropped, and the generated glue will be better: typedef void IfThisReturnsItHasErrored;
IfThisReturnsItHasErrored mainloop(); |
@ShE3py But sometimes as in the linked Stack Overflow question, people want a proper type with privacy and maybe generics. And I agree we should not allow all types that are ZSTs, especially types we do not guarantee are ZSTs (like the enum), but for types that we do guarantee they will be ZSTs I think it makes sense to guarantee that returning them is equal to returning |
This seems to works: use std::marker::PhantomData;
#[repr(C)]
pub struct Invariant<'a> {
_priv: (),
_phantom: PhantomData<fn(&'a ()) -> &'a ()>
}
#[forbid(improper_ctypes_definitions)]
pub extern "C" fn foo<'a>() -> Invariant<'a> {
Invariant { _priv: (), _phantom: PhantomData }
} example::foo:
ret I think it denies |
|
@ShE3py The issue with using a |
@Nilstrieb I don't think your point applies here. If we have #[repr(transparent)]
struct TwoZSTFields((), PhantomData<()>); which field is "the inner type"? The documentation seems to suggest that using
In the Rust Reference, the wording is similar; there must be a single non-zero-sized field. There is an open pull request on this topic here which seems to be in limbo. |
@ShE3py This code is invalid to begin with.
@Nilstrieb API and ABI stability are separate concerns. Yes, a type can stop being a ZST and it's ABI would change from that of |
Currently, for
extern "C"
functions returning ZSTs the compiler returnsvoid
(as well as for other ABIs, but this is not related). However,improper_ctypes_definitions
fire for such functions (if they don't return()
), e.g.:Playground.
It's pretty clear we do not want to guarantee the FFI-safety of ZST arguments. But what about the FFI safety of ZST return types? Do we want to guarantee they'll keep translating to
void
, or keep this not guaranteed?Context: https://stackoverflow.com/q/76950446/7884305.
@rustbot label T-lang
The text was updated successfully, but these errors were encountered: