[not a Pre-RFC]: Opt-out safety for experienced developers

Current safe abstractions have hidden costs (bounds checks, initialization, synchronization). I've implemented truly zero-cost alternatives. Benchmarks show 100% improvement in cases where the program doesn't crash.

  • immortalize() - extends any lifetime to 'static for when you know better than the compiler
  • clone_mut() - creates multiple &mut references when you need aliasing
  • garbage() - returns uninitialized memory for performance-critical code
  • RacyCell - like UnsafeCell but implements Sync for convenient concurrent access

Reference implementation: GitHub - buyukakyuz/corroded: Illegal rust

I believe Rust's safety guarantees, while useful for beginners, can be an obstacle for systems programmers who understand memory. This would be similar to how C++ trusts developers by default.

PS: Memory safety is well-studied, but what about memory freedom?

8 Likes

everything there is unsound, and there is even instant-UB.

then I read the Notes for LLMs in the readme and I approve of that repo. LOL

13 Likes

Consider this as community service.

4 Likes

The point of Rust is to have the opt-out contained to unsafe blocks, which can be hidden behind safe interfaces.

That's not for performance – safe doesn't have to be slow. That's to allow the compiler to check the assumptions automatically wherever the code is used, and prevent unlimited and implicit spread of dangerous code and risky assumptions that developers need to know about and manually uphold.

If you break the rules of safe code, e.g. by exposing a temporary reference as non-temporary 'static, then you're not only risking UB and miscompilations, but you're diminishing the benefit if safe/unsafe split. Now the dangerous dangling pointer can be anywhere, and any code can end up using it incorrectly by accident, not just unsafe code.

If you want to opt-out of safety, just wrap everything in unsafe and use unsafe fn. You can still do all the C++ crimes, but don't expose them as "safe" to corrupt the language-wide guarantees.

Also keep in mind that C++ is full of things you're absolutely not allowed to ever do (Undefined Behavior). C++ doesn't trust you with these. It will end up punishing you for invoking UB. Your code doesn't just run on your hardware. It is first run symbolically during optimization on an abstract C machine which has UB for real, and doesn't behave like your real hardware. This can make the code behave in ways that don't make sense on the real hardware. Rust inherited a lot of that via LLVM, so when you invoke UB in Rust by violating safety rules, you will also risk miscompilation created by LLVM because the abstract rules allow it to, even if the actual hardware doesn't care if memory is uninitialized or pointers are dangling. LLVM does and it will do weird stuff when it notices it.

Causing UB is a mistake in both C++ and Rust. Don't do it.

6 Likes

I'd like to kindly remind you that this is a joke. But thank you for the viewer discretion.

3 Likes

Problem is it's really not clear that it's a joke.

10 Likes

Interesting, okay.

These kind of posts are more appropriate in other forums where this was already posted to earlier.

The problem with jokes like these is that we regularly see people making this argument in earnest.

18 Likes

Maybe if you haven't spent more than two seconds looking at the README in the repository.

1 Like

I believe a significant amount of users (me included) tend to respond to forum posts as-is, without reaching out to the linked material.

3 Likes

For quite a lot of this, there's prior art, which you should take into account when not submitting the RFC:

This one was actually in the real Rust at one point (mem::uninitialized), but was massively deprecated because it was too difficult to specify it correctly (which made it too dfficult to use because you had to work around the issues caused by the implementation being written to an unclear specification).

This one's in nightly at the moment: SyncUnsafeCell. Massively unsafe if used incorrectly, but a useful building block to build unsafe abstractions out of and enclose in safe wrappers. (For example, I recently wrote some code which was basically an UnsafeCell guarded by a custom mutex implementation, and was meant to effectively recreate Mutex but implemented differently. Because I was writing the code on stable, only UnsafeCell was available to handle the "inside" of the mutex, so I had to unsafe impl Sync on it and that created a risk of getting the trait bounds wrong. If the inside were a SyncUnsafeCell – which would have been safe because I knew the restrictions preventing it being accessed from multiple points at once would also prevent it being accessed from multiple threads at once – the auto-traits would have been correct already and I wouldn't have needed an unsafe impl that's a potential bug risk.)

The API on this one is wrong: it should not return the &mut references directly, but rather return them via outpointers provided by the caller. I have written a blog post about how to use aliasing &mut correctly. (Strangely, the blog post isn't a joke – rather, it's a discussion about how you could implement shared references in a hypothetical version of Rust that lacked them, an exercise that is interesting because it provides insights into what the correct way to define shared references is, and thus into the mathematical basis behind them.)

5 Likes

Really didn't know these exist. Thank you for the reference.