Closed gnzlbg closed 5 years ago
I would prefer not to enable features as soon as they land on a stable compiler, because that forces everyone to upgrade to the latest compiler, and sometimes teams can't upgrade right away or have valid reasons for delaying upgrades. That's not to say that this isn't a valid solution, just that we should be considerate of teams that might not be able to upgrade right away.
What ABI issues are you referring to and how does repr(packed)
solve them?
That's not to say that this isn't a valid solution, just that we should be considerate of teams that might not be able to upgrade right away.
This is a breaking change, so it is going to require a major semver version bump (from 0.x to 0.x+1 until mach achieves 1.0). If a team cannot upgrade right away, they should just not update their Cargo.toml
to target the next version. Or in other words, this does not force anybody to upgrade.
What ABI issues are you referring to and how does repr(packed) solve them?
Some of the mach structs have an alignment of 4 in x86_64
targets. Without packed, they have an alignment of 8 in Rust, and a slightly larger size.
First, this is undefined behavior, leads to reading/writing garbage, and it is why I would like to support this as soon as its available on nightly. Without this, only x86 32-bit targets can use mach without undefined behavior (that is, you can only really target i686-apple-darwin
safely right now).
In practice, Rust just typically inserts some padding after the first struct field, while C does not because in C the structs are pack(4)
. The consequence is that all fields after the first one in both C and Rust do not point to the same bytes. This is bad. If you pass via the C API a pointer to a struct, C won't write to the struct fields but somewhere in between fields, or potentially out-of-bounds. When you read in Rust from these structs, you are typically reading a mixture of the actual field, padding (garbage), and other fields.
This is a breaking change, so it is going to require a major semver version bump
That's part of the solution, but it's easier than you're letting on to accidentally force a team to upgrade by merging new features after a breaking change. I would add that we should try to get new features and bug fixes into the current version before making the breaking change. It sounds like you're already thinking in this direction, given #22, so I think we're on the same page here.
Some of the mach structs have an alignment of 4 in x86_64 targets. Without packed, they have an alignment of 8 in Rust, and a slightly larger size. ... because in C the structs are
pack(4)
Got it. Thanks for explaining. I just didn't see any details beyond "ABI Issues" anywhere, so I didn't know what was being discussed. This makes sense.
It sounds like you're already thinking in this direction, given #22, so I think we're on the same page here.
Yes we should definitely do a minor release of the last commit of the 0.1 series. That was: https://github.com/fitzgen/mach/commit/592d9e995f46195f2b87bdeae3c316e125f7db2a (the commits afterwards start fixing ABI issues like missing repr(C)
, missing struct fields, etc).
Okay. I was looking at #30 as something that adds new APIs that would be nice to merge first, but if master is already tracking 0.2, then no worries. It's not worth it to backport. I was also going to suggest tagging issues with milestones to track what's slated for each release series, but sounds like everything going forward will be 0.2.
@gnzlbg Thanks for catching and fixing these issues and then taking the time to explain them. As it stands, I have no objections to the direction this is headed.
Status update: all the methods and types that required repr(packed(N))
to avoid undefined behavior were deprecated from the library in version 0.2, so people using that should have been getting a warning for a while. They have been able to silence this warning either by allowing deprecated items of mach
, or by enabling the unstable
feature which requires a nightly Rust toolchain.
Version 0.3 only exposes these types and methods behind the unstable
feature. When repr(packed(N))
lands on stable we can remove the unstable feature and release a new version.
So I needed to use mach
from libstd
, so went on and released version 0.3
which always uses repr(packed(N))
and is also always #[no_std]
. Migrating from 0.2 to 0.3 should be painless, since all "breaking" changes have had a deprecation warning since november last year. Please let me know if there are any issues.
All the remaining ABI issues cannot be easily solved without
repr(packed)
. We could use an opaque type and then add methods toget
/set
its fields but, that's too much of a hack given thatrepr(packed)
will be merged shortly.The best we can do is probably add a
build.rs
that enablesrepr(packed)
whenmach
is compiled using a nightly compiler. And oncerepr(packed)
is stabilized we just enable it unconditionally.