Hacker News new | ask | show | jobs
by ultimaweapon 506 days ago
Actually 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.
1 comments

That's... not what the issue is, that is the bare minimum expectation.
But then again: for a language as bare-bones as C, what more is there really to a good FFI system?
The 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.
You 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?

I think your understanding is correct - for Rust to work well in Linux, the C maintainers need to maintain more discipline than has been absolutely required before (in that if they've changed those semantics then any breakage has been largely silent and any bugs created have potentially been subtle), and changing that is a social problem more than a technical one because there's no technical mechanism to enforce the same rigor on C. The attempted tradeoff of "The bindings are up to the Rust developers" is something that only really works if the C developers are willing to accept that additional constraint.

(To be clear I have spent many nights drinking with Christoph and think he's entirely in the wrong here)

As a non-Rust dev, what is the issue with C interop?
Roughly the same problems as C++ interop, you can't map common Rust concepts (like error unions, optionals, tagged-union enums, ptr/length-strings, traits) to C APIs without an intermediate shim which does potentially expensive and brittle marshalling, and the C-API is also a 'visibility barrier' for the Rust compiler when it comes to Rust concepts like RAII and ownership tracking.
I think C++ is worse actually due to the lack of move constructors in Rust (move is always memcpy). It means you can't e.g. return std::string by value.

The issues with C FFI are comparatively minor and not at all unique to Rust. Hell, even C++ has those issues when interacting with C APIs. It's not like a std::variant magically becomes a tagged union.

> Hell, even C++ has those issues when interacting with C APIs

That's what I meant but poorly expressed (e.g. C++ <=> C interop has roughly similar problems as Rust <=> C interop).