-I also added a special exception: When "creating a raw reference"
-(`EscapeToRaw`, or `Retag` on a shared reference when we are inside an
-`UnsafeCell`), we still first check that the pointer this reference is created
-one is allowed to be dereferenced -- and we remember the position of the item on
-the stack that justifies this, let's call this `ptr_idx`. Remember, that does
-not change the stack, so it has no adverse effect in `demo_refcell`. Next, we do
-a very peculiar check:
-
-1. Determine if the new reference we are creating (it will have a `Shr` tag) is
- *already dereferencable*. This is possible, for example, if the location
- already got shared previously. This is also the case in `demo_refcell`:
- Creating `rc_shr` pushed a `Shr` onto the stack. We again remember the
- position of the item that justifies this, let's call it `new_idx`.
-
- - If this is the case, we moreover *compare* the `new_idx` and `ptr_idx`.
- If `new_idx` is *above* `ptr_idx` on the stack, that means that not only
- is the location already being shared (so we can dereference with our new
- `Shr` tag), moreover *the pointer we create this reference from has
- already been shared*. The new pointer is already "derived from" the one
- this reference is based on. Basically, everything that we wanted to do
- while creating this reference has already happened. In this case, we just
- do nothing else: We leave the stacks unchanged.
-
- - Otherwise, we continue as usual.
-
-This rule has the effect that in our example above, when we create `shr_ref`, we
-do not pop `Uniq(2)` off the stack, and hence the access through `mut_ref` at
-the end remains valid.
-
-This may sound like a weird special case, and it is. I would surely not have
-thought of this if `RefCell` would not force our hands here. However, it also
-does not seem to break any of the important properties of the model (mutable
-references being unique and shared references being read-only except for
-`UnsafeCell`).
+I also added a new check to the retagging procedure: Before taking any action
+(i.e., before step 3, which could pop items off the stack), we check if the
+reborrow is redundant: If the new reference we want to create is already
+dereferencable (because its item is already on the stack and, if applicable, the
+stack is already frozen), *and* if the item that justifies this is moreover
+"derived from" the item that corresponds to the old reference, then we just do
+nothing. Here, "derived from" means "further up the stack". Basically, the
+reborrow has already happened and the new reference is ready for use, and
+(because of that "derived from" check), we know that using the new reference
+will *not* pop the item corresponding to the old reference off the stack. In
+that case, we avoid popping anything, to keep other references valid.
+
+It may seem like this rule can never apply, because how can our fresh tag match
+something that's already on the stack? This is indeed impossible for `Uniq`
+tags, but for `Shr` tags, matching is more liberal. For example, this rule
+applies in our example above when we create `shr_ref` from `mut_ref`. We do not
+require freezing (because there is an `UnsafeCell`), there is already a `Shr` on
+the stack (so the new reference is dereferencable) and the item matching the old
+reference (`Uniq(0)`) is below that `Shr` (so after using the new reference, the
+old one remains dereferencable). Hence we do nothing, keeping the `Uniq(2)` on
+the stack, such that the access through `mut_ref` at the end remains valid.
+
+This may sound like a weird rule, and it is. I would surely not have thought of
+this if `RefCell` would not force our hands here. However, as we shall see in
+[section 5], it also does not to break any of the important properties of the
+model (mutable references being unique and shared references being read-only
+except for `UnsafeCell`). Moreover, when pushing an item to the stack (at the
+end of the retag action), we can be sure that the stack is not yet frozen: if it
+were frozen, the reborrow would be redundant.
+
+With this extension, the instructions for retagging and `EscapeToRaw` now look
+as follows (again executed on all locations covered by the reference, according
+to `size_of_val`):
+
+1. Compute a fresh tag: `Uniq(_)` for a mutable reference, `Shr(Some(_))` for a
+ shared reference, `Shr(None)` if this is `EscapeToRaw`.
+2. Perform the checks that would also happen when we dereference this reference.
+ Remember the position of the item matching the tag in the stack.
+3. Redundancy check: If the new tag passes the checks performed on a
+ dereference, and if the item that makes this check succeed is *above* the one
+ we remembered in step 2 (where the "frozen" state is considered above every
+ item in the stack), then we stop. We are done for this location.
+4. Perform the actions that would also happen when an actual access happens
+ through this reference (for shared references a read access, for mutable
+ references a write access).
+ Now the location cannot be frozen any more: If the fresh tag is `Uniq`, we
+ just unfroze, if the fresh tag is `Shr` and the location was already frozen
+ then the redundancy check (step 3) would have kicked in.
+5. If the new tag is `Uniq`, push it onto the stack.
+6. If the new tag is `Shr`, push a `Shr` item to the stack. Then, if the
+ location is outside of `UnsafeCell`, it gets frozen with the timestamp of the
+ new reference.
+
+The one thing I find slightly unsatisfying about the redundancy check is that it
+seems to overlap a bit with the rule that on a *read* access, a `Shr` item
+matches a `Uniq` tag. Both of these together enable the read-only use of
+mutable references that have already been shared; I would prefer to have a
+single condition enabling that instead of two working together.