> We're probably going to see "unsafe" code that assumes good behavior on the part of the caller.
I have yet to see any of this.
I have noticed that it's harder to write correct unsafe code when it comes to parallelism and FFI, but parallelism has always been a hard problem and the FFI problems generally come from the fact that you need to know the invariants being upheld on the other end, which is trickier.
But for this kind of unsafe code -- designing (non-parallel) abstractions -- upholding invariants is pretty straightforward.
I would say that this is from a time when the invariants were not understood. In particular, the fact that leaking is safe to do in safe code was not known.
(The invariants are still not completely understood, but there's work to specify that, and IMO they're understood enough to be able to avoid unsafe bugs)
> BTreeMap::range still has an UB bug from trusting the caller!
> I would say that this is from a time when the invariants were not understood.
Yeah, but it's not like "oh this is an obvious thing to consider trusting the caller about". It's an exceptionally niche problem that you'd only know about if someone told you about it. Especially since a Rust programmer shouldn't be expected to write unsafe code often, if ever!
Similarly: not trusting traits to be implemented correctly. Not trusting closures to not-unwind.
Fair. I'm not saying that your average Rust programmer will be able to deal with unsafe code immediately. But I do think that at this stage the list of things you can and cannot rely on (and the invariants you must uphold) is clear enough that in theory you could make a checklist to deal with this. The nomicon provides much of the background for folks wanting to figure this out and write unsafe code.
These days I've been writing a lot of unsafe code (for FFI) and I do want to get around to penning a concise guide (or just expanding the nomicon). But I'm mostly waiting for the unsafe code subteam to figure out a couple things before doing this (specifically, the exact boundaries of rust's noalias UB becomes important in FFI and this is not specified yet).
But yeah, it's not necessarily obvious. I'd like to make it easier to get this understanding of unsafe code though.
One of the barriers I've erected in my own head is whether my unsafe code is generic or not. As soon as your unsafe code starts depending on an arbitrary T (or some trait that T satisfies), then the scope of what you need to consider seems to widen quite a bit. I tend to either avoid this type of unsafe or find a way to constrain my problem. Using `unsafe` for pointer tricks or efficient movement of memory on concrete data types feels more self-contained to me, and therefore easier to verify.
(I don't have any particular point to make btw. Just sharing thoughts.)
I have yet to see any of this.
I have noticed that it's harder to write correct unsafe code when it comes to parallelism and FFI, but parallelism has always been a hard problem and the FFI problems generally come from the fact that you need to know the invariants being upheld on the other end, which is trickier.
But for this kind of unsafe code -- designing (non-parallel) abstractions -- upholding invariants is pretty straightforward.