Last week, LWN published “READ_ONCE(), WRITE_ONCE(), but not for Rust”, which described an issue encountered as part of integrating more Rust into the Linux kernel: namely that the READ_ONCE and WRITE_ONCE macros are in practice used for diverging purposes in different contexts, implicitly encoding an inconsistent set of semantic guarantees. The article then describes how the Rust contributors to Linux are working to determine how to more accurately express the specific semantic guarantees associated with the Rust-side of APIs which use these macros on the C-side.
This situation, of identifying an API which is implicitly encoding multiple distinct semantic guarantees, and thereafter wanting to disentangle them, is a familiar one for Rust developers. One little-discussed cultural norm in the Rust ecosystem is that APIs should be designed to encode semantic guarantees as precisely as possible.
This is shown in things like the design of container types, such as Rust’s various “cell” types (Cell, RefCell, OnceCell, etc.), as well as pointer-associated types such as Unique (internal to the Rust standard library, where it is used heavily) or NonNull (part of the std::ptr API). As Manish Goregaokar described in “Wrapper Types in Rust: Choosing Your Guarantees”, Rust tries to disentangle unique semantic guarantees which users can then compose together to express precisely what they need.
It also appears in Rust’s ongoing discussion around amending the Copy / Clone trait hierarchy to enable more precision. Copy is a trait intended for types which are trivially-copyable, meaning their full contents can be copied with a single memcpy. Clone is intended for more “expensive” copies, for example copies which require duplication of data on the heap and adjustment of pointers to point to the copied data. Over time, Rust developers have identified types with a different sort of copy semantics, such as Rc or Arc, where cloning the data in fact means cloning the handle to the underlying data, not the data itself.
The Rust community’s desire for precise semantics, in the long run, leads to more robust software systems. In the short run, as the Linux devs are encountering, it can be challenging to introduce greater semantic precision in systems which were previously more ambiguous about guarantees and requirements. Personally, I’m glad Rust has this norm, and it’s something I find appealing about Rust as a culture, not just a language, and I remain optimistic that Linux will be better off because of it.
Copyright Andrew Lilley Brinker. Made with in California