4 ms·
I like Rust, but my worst experiences with Rust are interop with C. From this LWN article, some people seem very very stubborn against including Rust in Linux.
by kaladin-jasnah 2y ago
I like Rust, but my worst experiences with Rust are interop with C. From this LWN article, some people seem very very stubborn against including Rust in Linux. As someone who really likes Rust, I must say its borrow-checker design, and other things like derive and proc-macros. Personally, if Rust people are willing to undergo the full burden of maintaining Rust in the kernel and not place undue burden on the C developers, I feel that it could be a good idea to include Rust. It seems a little petty to just block Rust as a blanket statement.
However, I must ask: is there a world in which interop didn't have to be so bad without hugely sacrificing memory safety? Is this a problem that Zig solves (I must be honest, I don't really know much about Zig)? What _is_ the better solution?
- Kostarrr 2y agoZug does not attempt to solve memory safety. It aims to be a better C
- flohofwoe 2y agoA bit more nuance please, Zig doesn't attempt to solve compile-time memory safety like Rust does, but at least it provides spatial runtime memory safety (but also doesn't have a builtin solution for temporal memory safety - except a debug allocator which catches most use-after-free attempts on the heap) - so tl;dr: Zig is much better than C or C++ when it comes to memory safety, but isn't watertight like Rust.
- nikbackm 2y agoSo similar in that regard to Herb Sutter's experimental Cpp2 perhaps?
- lmm 2y ago> However, I must ask: is there a world in which interop didn't have to be so bad without hugely sacrificing memory safety? You can't really make interop nicer than the lowest common denominator, and when one of the sides is C then that lowest common denominator is very low. Rust is one of very few languages that can potentially interop with memory-safe languages without having to completely buy into a common runtime - e.g. it's increasingly popular to write Python extensions in Rust and I believe there are now libraries for doing that without having to go via C - and when you have richer abstractions available on both sides of the line then you can make use of them. But to work with C you have to work like C, at least at the boundary.
- flohofwoe 2y agoIt's not "C - the language" but "C - the calling convention" that gets in the way of higher level languages. And it's actually also wrong to blame C alone, ABIs are mostly a convention between operating system and CPU vendors, C compilers have to play by those rules just as any other compiler that wants to output code that can call (efficiently) into operating system APIs (and we could just as well be stuck with Pascal calling conventions instead, which was used by 16-bit Windows versions).
- lmm 2y ago> ABIs are mostly a convention between operating system and CPU vendors, C compilers have to play by those rules just as any other compiler that wants to output code that can call (efficiently) into operating system APIs Yes and no. Unix has a very C-oriented ABI because it's written in and tied to C, and since Unix and C won other operating systems have felt pressure to make their ABI C-friendly. > we could just as well be stuck with Pascal calling conventions instead, which was used by 16-bit Windows versions If we'd gotten Pascal strings in the ABI that alone would have eliminated one major class of bugs.
- ultimaweapon 2y agoActually the interoperability is very good. C can directly call into Rust and Rust can directly call into C. Rust can construct any C type and can expose opaque pointers to C world.
- 3836293648 2y agoThat's... not what the issue is, that is the bare minimum expectation.
- gspr 2y agoBut then again: for a language as bare-bones as C, what more is there really to a good FFI system?
- mjg59 2y agoThe issue isn't just FFI - for example calling directly from Rust into C without any expression of the semantics means you have no mechanism for reasoning about ownership, and that removes many of the security benefits of writing code in Rust in the first place. If you have a strong description of the semantics of the C code then you can write Rust bindings that expose that, but you're then constraining the maintainers of the C codebase in terms of their ability to make arbitrary changes without considering the impact that has on the Rust consumers. Doing this badly is fairly easy, doing this well is hard.
- gspr 2y agoYou are obviously a far more knowledgeable person than I am, so please don't take the following questions as dismissive of your expertise. I'm genuinely trying to learn. > for example calling directly from Rust into C without any expression of the semantics means you have no mechanism for reasoning about ownership Right. But since C cannot express Rust's ownership semantics, could one really do better? Does that mean that as long as there's significant amounts of C in Linux, then Linux should never introduce any language with stronger semantics than C? That seems unfortunate. > and that removes many of the security benefits of writing code in Rust in the first place. I've always thought of the idea being that _as long as the necessary manual reasoning is correct_, downstream Rust users _do_ get those benefits. But of course interfacing with C, lacking the necessary semantics, requires the interface writer to manually assure them. Wouldn't anything more demand more than C can deliver? > If you have a strong description of the semantics of the C code then you can write Rust bindings that expose that, but you're then constraining the maintainers of the C codebase in terms of their ability to make arbitrary changes without considering the impact that has on the Rust consumers. OK, but that seems like a political/social/organizational aspect far more than a technical problem with C-Rust-interop?
- gspr 2y ago> I like Rust, but my worst experiences with Rust are interop with C. Could you elaborate? I find the interop to be quite nice. I mean, obviously, interop between any two languages cannot ever be "better" than the least good language at any one thing.
- flohofwoe 2y agoZig has some features to make C interop easier (for instance string literals are both ptr/length-slices and zero-terminated), but in general the problems are quite similar to Rust's. There is a subset of Zig types that is compatible with C APIs, but most higher-level Zig types (like slices, odd-width integer types, optionals, error unions...) can't be tunneled through or mapped to a C API... The main thing may be that the Zig compiler doesn't track ownership/lifetimes like the Rust compiler does, so it doesn't matter that this information would be lost at the C-API barrier.
- pornel 2y agoIn Rust, unsafe (unchecked) C interop is almost automatic. The hard part is in translating C code's high-level safety requirements into Rust APIs that enforce them. I'm talking about requirements that aren't expressed in the C syntax, but are arbitrary domain-specific rules defined in English by the C code's authors ("this function can be called only on Wednesdays"). These turn out to be hard, because they may not be precisely defined, and/or the conditions are complex and implementation-specific. That's less of language inteop problem, and more in creating formal definitions of informal documentation. Having said that, there are a couple of things that Rust made harder for itself: • Rust allows moving objects to a different address safely. C code often assumes objects never move and their addresses are unique and meaningful. If Rust had built-in support for immovable types, it wouldn't need Pin and macro hacks. • Rust's reference types require strict immutability or strict pointer aliasing (exclusive access), while C allows memory to be mutated from anywhere, and pointers to const don't mean the data is immutable. This prevents Rust from using its nice safe reference and slice syntax on memory externally mutated in surprising/clever ways (by memory-mapped hardware, shared mem, MMU trickery).