I think weak memory is of little concern here because all potentially racing accesses must happen through &UnsafeCell, so there is no freezing and no checking going on – everything is Raw.
Why do you think this is ruled out? The second reference would re-freeze, but that’s okay.
Uh, good question. The return value would be activated, and then that would be UB because the location is not frozen.
Aha! I agree. I want that, too, and I hadn’t thought about what happens.
If we would do things like freezing recursively through pointer indirections, things would work out as the inner T would be frozen anyway. But with the model as I described it, I think this cast would actually not be legal because, well, it’s a transmute of &mut T to &T, and then see above.
We could say that a shared reference, upon retagging, starts a freeze if things are not already frozen, but I am worried that this might weaken shared references because now we can no longer know that stuff has already been frozen.
Or we could make creating a shared reference (from an &mut) special in the sense that it is the only operation which proceeds recursively and freezes everything. But that also seems surprising, when nothing else recurses through references.
Note that at least in my mind, the tag is just a timestamp, it does not know whether it is Uniq or Frz. So transmuting a &mut T to a &T actually “reinterprets” the tag. Maybe the tag should come with that extra information as you seem to assume it does, and maybe that helps – retagging would activate the Uniq, but then freeze. I think that solution sounds best, from the ones I have seen so far.
I do not follow. The inserted write is visible to whoever passed you the &mut – someone else will have access again when you are done. Spurious writes are only okay if the reference is never used again by anyone else in the future. Am I missing something?
However, this means that we can only add noalias when we can show that the corresponding reference is never dropped.
Correct. I was focusing on aliasing in this post; the next post will be about which party can assume which invariants on types to hold when, and that’s when I am going to come to this point.
Agreed.
Ah, that is an interesting one – and a good case for doing some kind of validation recursively through references.
On the other hand, we have plenty of unsafe code that hands around references to not-completely-initialized data. So I am a bit worried about how such code might interact with this kind of optimization – not very well, probably.
Yes.
Making integers carry tags invalidates all sorts of arithmetic optimizations, so that is a no-go.
Raw pointers carrying tags that are being ignored would be fine though. However, that may or may not be enough for this situation, I would have to look at some examples.
This is a hard question in C, and it is juts as hard in Rust. We recently wrote a paper about it. I do not plan to solve those questions with this model.
The intent is that the compiler may optimize, but that has nothing to do with Rust’s reference types any more, this is the usual reasoning that you would also do in C about not being able to guess addresses.