Hi folks.
I’ve have two issues related to repr
and a request that seems not-hard, but could totally be shot down.
Issue 1: I use Abomonation a bunch for serialization (and will continue to do so, until something with similar speed/ergo shows up), and it makes some assumptions about the stability of field layout. I’m comfortable (note: not “happy” :)) with the requirement that field layout is stable within a binary, and not expecting anything between binaries, but it would be really helpful to have some constancy across builds. It is a pain to put #[repr(C)]
on all types, partly because (i) it is meant to be a light touch, and (ii) many types are system-provided (it would suck to not get to use String
or tuples, etc.).
Issue 2: I’ve recently become interested in Rust shared libraries, as a way to modularly load up dataflow graphs. The interface is really narrow: the library code provides a method that builds a graph if handed an Allocator
, and the server binary loads libraries and calls into these methods. However, the Allocator
can mint channels of arbitrary types, and everything goes off the rails if the library and server binary have different opinions on the layouts of these types. Or if a second library which receives the data has a different opinion. Again, you could put #[repr(C)]
on literally every type that you use, and avoid system types, but this seems like a horror.
Both of these issues suffer from the fact that repr(C)
is not a trait, and so I can’t actually require it, and so things would just silently fail when field orders get monkeyed with. The library/server code I’ve written is like 20 lines total, issues no warnings, and just wont work correctly once Rust starts changing field orders around. There is absolutely unsafe
in both pieces of code, so the problem isn’t “Rust is not behaving correctly” so much as “Rust makes it very hard to write correctly behaving code”.
Ask: It seems not too hard (and please correct me once you’ve finished laughing) to indicate something like a binary-wide #repr(C)
on all introduced types. For example, a Cargo.toml field or rustc parameter. All of the discussion on field re-ordering has made it sound like these options aren’t so hard to tweak, so maybe this wouldn’t be a tragic undertaking. My understanding is that std
already has an opinion on its types and this isn’t something I can change, but it would be nice to be able to request a stable ABI for the nonce.
The request is not to have Rust commit to an ABI, but just a Cargo.toml entry or something that results in a consistent (if unspecified) field layout for … say any given version of std. I understand that (some of) you would prefer not to have anyone rely on field ordering, but loading and using shared libraries is really not meant to be some abusive use of underspecified internals.
I wanted to write some alternatives here, but I couldn’t think of any. What I really hoped was that #repr(C)
would be transitive, requiring nested fields be repr(C)
also so that I could wrap types that might transit binary boundaries, and restrict channel/serialization to such types. Apparently that doesn’t work, though.