Hacker News new | ask | show | jobs
by ekidd 690 days ago
I would be really careful with those deref methods. They return references, not pointers, which means you need to follow the Rust rules:

- You can have any number of simultaneous readers,

- Or one writer and no readers.

- But if you ever break these rules, the world may burn.

Using unsafe and violating these rules is one of the cases where the Rust compiler can inflict worlds of misery: Incorrect code generation, CPUs seeing different versions of the same memory location, etc., depending on the exact context. Once you use "unsafe" and break the rules, Rust can be more dangerous than C. Rust even reserves the right to generate code using "noalias" (except doing so often triggers LLVM bugs, so it's usually turned off).

"Undefined behavior" means "anything at all can happen, and some of it is deeply weird and awful and counterintuitive."

You could enforce the borrowing rules at runtime by using std::cell::Cell in your heap objects, which is exactly what it exists for. Or you could package everything inside a tiny core module and audit it extremely carefully.

3 comments

You would probably want to use RefCell instead of Cell. It allows you to safely upgrade into a &mut using only a constant reference to RefCell, but it dynamically verifies that it's actually safe using ref counting. The ref counting also isn't too expensive since it isn't atomic.
> (except doing so often triggers LLVM bugs, so it's usually turned off).

It's been enabled for a couple years now.

I'm aware of all the issues mentioned. But for this particular project, I simply don't care as long as it passes Lox's test suite xD. I went this path just to see how easy it is to get tripped by unsafe while knowing that there's a technique to get safety with Pin<T> that this can get refactored into. I actually implemented this with Cell and RefCell but didn't find that interesting.