Comment by adwn
8 days ago
True, but unsafe let's you conjure up any lifetime you want, or any lifetime necessary to satisfy the lifetime requirements in safe code. If you generously sprinkle pointer dereferences in unsafe code, you effectively disable the protection provided by the borrow checker – including in safe code – until you've checked and verified the correctness of all unsafe blocks.
> True, but unsafe let's you conjure up any lifetime you want
The only thing unsafe does is let you have an unbounded lifetime. As I said, it doesn't check those:
https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html
> if you generously sprinkle pointer dereferences in unsafe code, you effectively disable the protection provided by the borrow checker
You don't disable anything. You wrote a "trust me compiler" block, and compiler trusted you.
Rust won't ever protect from all possible problems, just the ones the compiler handles.
> You don't disable anything. You wrote a "trust me compiler" block, and compiler trusted you.
That’s the same thing.
What's the point of using Rust in the first place when you disable the compiler feature that protects you the most?
Because it lets you constrain the parts that the compiler can’t check and has to trust you on. The alternative is either a langue that can’t do necessary things, or a language that can’t check what could be checked.
With unsafe, you’re telling the compiler “I’ve taken extra care to make sure that what I’m doing is safe and doesn’t break your rules” and the compiler can go ahead and assume that you don’t, in fact, break the rules, and therefore can verify everything else as if the rules never got broken.
In less safe languages, the entire program is “trust me, it’s safe”, while in rust only the parts flagged as unsafe are.
The point is that you should only use unsafe when 1. It’s absolutely necessary for functionality or performance and 2. You have verified and are very certain that the code is correct.
That’s a very useful property to have.
2 replies →
Well, Rust has things like miri that can help you write your unsafe code and it's just a command line invocation away.
Obviously you should try to avoid writing unsafe Rust to begin with.
Mu. Invalid question. Rust doesn't disable compiler features. It gives you extra set of footguns when you ask for it.
As for the actual unloaded question, "What's the point of unsafe in Rust?" it is to contain and make it easier to identify sources of UB.
2 replies →
> The only thing unsafe does is let you have an unbounded lifetime.
No, you're wrong: You can create any lifetime. Proof:
This will take a reference and return it with any lifetime specified by the caller.
> You don't disable anything.
I said "effectively disable". For example:
fn trust_me_bro<'a>(x: mut u32) -> &'a mut u32 { unsafe { &mut x } }
After the call to trust_me_bro, two aliasing, mutable references exist simultaneously. This would usually be prevented by the borrow checker, but the unsafe code has effectively disabled it.
> Proof:
You just listed examples of unbounded lifetimes.
> I said "effectively disable". For example:
Not sure what you meant by this example since it doesn't compile. It seems the borrow checker caught your mischief. So much for effectively disabling stuff :P
You haven't effectively disabled anything; you just (tried to) wrote unsound code that washes one mutable ref as another. This stuff is allowed provided shared refs are never accessed at the same time (for example, panicking upon reading reference_b).
What you probably meant is https://play.rust-lang.org/?version=stable&mode=debug&editio...
But you know what? If you're dabbling in unsafe, you have this big button called Tools in the playground. Choose Miri, then run your code; it will display large Undefined behavior. It even highlights the `trust_me_bro` function.
Hell, run this with UBSAN, ASAN, and other C tools. They will probably catch any such behavior.
2 replies →