I guess it’s a bit silly, but c_void
could alone go into libcore.
I think c_void
and c_char
should be in core
. The fact that compilers allow for changing the signedness of char
via a commandline flag isn’t really an issue unique to Rust. The platform has to pick a default for compiled code and overriding that default will cause the same incompatibilities with existing C code as it would with existing Rust code.
As for the other types, I would initially be conservative and put them in a ctypes
crate between core
and std
.
Many of the strategies we’ve been discussing recently involve putting the definition of c_void
“under” std
, either via core
or a new ctypes
crate. Then both std
and libc
could use this shared definition.
In the initial post, @bluss claimed that repointing libc
to a shared definition like that would require a major version bump in the crate. (There was a further claim that a major bump will eventually be needed for one reason or another, but let’s put that aside for the moment.)
Questions:
- Is such a major version bump strictly necessary? Why?
- If we have to do a major bump to
libc
, isn’t that likely to cause at least as much pain as deprecatingstd::os::raw
in favor oflibc
would?
In my opinion, changing libc::c_void
to be a reexport of a c_void
from a higher up crate would not be a breaking change. I can’t imagine how any code could rely on the assumption that the type isn’t a re-export and be broken by that change.
- My idea was that
libc 0.2.16
and libc0.2.17
need to have compatible c_void definitions. That seems to be a misunderstanding actually, since you wouldn’t use both of those in the same project (and if you do, their c_voids are incompatible anyway). - A major bump in libc is planned anyway (1.0), so that’s not an issue.
So with that out of the way, I feel like @alexcrichton’s arguments against putting types in core
don’t apply to c_void
, which happens to be the only type for which the location matters.
Thus, if we want to solve this problem quickly and with minimal pain and commitment, the most plausible routes seem to be one of the following:
- Introducing a
ctypes
crate understd
with all ofstd::os::raw
in it. - Adding
c_void
alone tocore
, which doesn’t require weighing in on various C issues but solves the main problem.
If we are motivated to remove std::os::raw
from std
(perhaps for the reasons @alexcrichton laid out), I think the ctypes
approach is the best solution. We could take the following steps:
- Introduce the
ctypes
crate into the Rust distro, and makestd
re-export its definitions instd::os::raw
. - Update
libc
to also re-export those types, with a minor version bump.- Note: this is a bit tricky since it requires a particular version of the Rust distro to work; we’d probably need some way to deal with that, either via detection or feature flags.
- Now, the world of
libc
andstd::os::raw
types are fully compatible, solving the original problem. - At this point, we can safely deprecate
std::os::raw
in favor ofctypes
, and perhaps at some later date remove those deprecations in a major version of Rust.- This deprecation no longer causes massive pain, because you can switch to the
libc
(orctypes
) definitions without breakage.
- This deprecation no longer causes massive pain, because you can switch to the
Thoughts?
Overall that plan seems reasonable to me, but diving into the details on this one may show that it's pretty tricky. We could actually switch these to reexports today, except that libc
now has a feature to support #![no_std]
. I would feel pretty bad about reexporting if you link to std and defining if you don't, and it also seems like it could cause confusion/breakage.
That is, we may not be able to switch libc
to reexport until the ctypes
crate is stable, unless we're willing to define some of the time and reexport the rest of the time.
Are there any arguments against doing this?
I would personally avoid doing so as it seems “pretty weird” that sometimes libc defines these types and other times it doesn’t. There is indeed subtle breakage that can happen by defining a new type vs reexporting another. A silly and contrived example is impl LocalTrait for libc::c_void
plus impl LocalTrait for std::os::raw::c_void
, where that will compile with #![no_std]
and it won’t compile if libc links to std.
That, and it still doesn’t solve the problem of “one source of truth” for these types (which is the original crux of this issue). If we do that then I would think that we’re basically where we are today, with the “pain” just shifted somewhere else.
I think it sounds good. A ctypes crate is more than c_void needs, but from the discussion here it sounds like the best solution.
Hm so another possible snag is that ideally libc
never links to libstd. That is, the use_std
feature just shouldn’t exist because the library never needs std
(it was just left in for backwards compatibility in niche use cases).
Ongoing discussion has moved onto that RFC.
@jethrogb, apologies for the long delay resolving this issue. It fell off my radar.
RFC https://github.com/rust-lang/rfcs/pull/1783 was eventually closed/postponed.
New RFC to propose fixing this through core::ffi::c_void
: https://github.com/rust-lang/rfcs/pull/2521
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.