Hacker News new | ask | show | jobs
by stouset 945 days ago
At the risk of sounding like I’m trying to “defend Rust with whatever it takes”, your argument seems bizarre to me.

Even at the surface, if your desired solution is so antithetical to the type of structure that Rust tries to push you towards, you can quite literally just write this component of your code as if it was C. Just using pointers instead of borrows and tag all your functions as unsafe and… pretend you’re writing C? At that point you’ve, I think, more or less disabled 95%+ of the bits that would prohibit you from writing code exactly as you would in C. You don’t get the benefits of Rust for that part, but at least you get them for the remaining 80%.

Or you can very literally just write the “hard part” in C and call it from Rust. You might have to make sure you can’t panic across language boundaries, but other than that the C interop is just about the best I’ve seen from any language.

I also don’t entirely understand how unsafe can be 1,000x more (or even 1.5x more) error prone than C. But I’d love to hear how. The only “trick” to unsafe is that you should aim for your unsafe blocks to be “unit-safe”. Meaning they might do something unsafe inside, but from the outside looking at it as a black box, the unit functionality of it should be safe. I don’t think the docs do a good enough job here of encouraging that style of design. You can violate this guideline, but doing so without sufficient care is quite likely to result in bugs. But of course if you did the same approach in C, you’d have a similar outcome.

The only real way I can reconcile your points is if the performance-critical bits that seriously impact the design of your program are scattered uniformly and don’t have anything resembling clean boundaries. I suppose that’s a real possibility but it does seem very foreign to me.

1 comments

Yeah see, that is what I thought at first as well.

I sort of imagined that I could get the best of both world, and just "unsafe { <C style code> }" my way out for performance critical things.

But the thing is, the static safety boundaries of Rust allow the compiler to make much, much tighter assumptions than C & C++, especially around aliasing rules, un initialized memory, and moves.

When you relax these boundaries with "unsafe {}", you don't enter "C world", you enter the litteral gates of hell where any innocent temporary cast can throw you in a random load/store reordering bug.

Do you mean innocent temporary cast from a pointer to a reference? Cause yeah, those aren't innocent. And that's a newer realization and there were serious documentation issues around it.
Thanks for the reply. I think if you combine unsafe with raw pointers instead of borrows you relax the rules enough to avoid this. But in this specific corner of things, I haven’t had direct experience so you may very well be right.

There are still some Rust-specific details you would still need to handle—as you mentioned, uninitialized memory—but for that one specifically I haven’t found MaybeUninit to be particularly cumbersome.