In rust, &mut T
is not normally allowed to refer to aliasing memory. But when writing self
referential structs, one needs aliasing mutable references. This crate provides the
[UnsafeAliasCell<T>
] primitive type. It works similar to the [UnsafeCell<T>
] from the
&UnsafeCell<T>
may point to data that is being mutated.
[UnsafeAliasCell<T>
] opts-out of the uniqueness guarantee for &mut T
: a unique mutable reference
&mut UnsafeAliasCell<T>
may point to data that is being mutated.
UnsafeAliasCell<T>
]One needs to be careful, when using [UnsafeAliasCell<T>
], because wrong usage leads to undefined
behavior.
Even when using [UnsafeAliasCell<T>
] it is considered undefined behavior to create multiple
aliasing &mut T
. But you are allowed to create multiple aliasing *mut T
/*const T
.
Use [UnsafeAliasCell<T>
] on the part that you intend to alias:
```rust
pub struct SelfReferential {
item: UnsafeAliasCell
Now you are allowed to call [
.get()] on
itemand store that pointer in
ptr. For as long as
that
SelfReferentialstays [pinned](https://doc.rust-lang.org/std/pin/index.html), you can use
ptr` to read the item.
Implementing [Unpin
] for any type containing a [UnsafeAliasCell<T>
] is UB.
It is UB to cast the pointer returned by [.get()
] to
- &mut T
, when there exists another pointer (&T
, *const T
or *mut T
) pointing to the inner
of the cell.
- &T
, when there exists another mutable pointer (*mut T
) pointing to the inner of the cell.
Similar to [UnsafeCell<T>
] you need to ensure the aliasing rules for any reference you create
(taken from the [stdlib]):
'a
(either a &T
or &mut T
reference) that is
accessible by safe code (for example, because you returned it), then you must not access the data
in any way that contradicts that reference for the remainder of 'a
. For example, this means that
if you take the *mut T
from an [UnsafeAliasCell<T>
] and cast it to an &T
, then the data in T
must remain immutable (modulo any [UnsafeCell<U>
]/[UnsafeAliasCell<U>
] data found within T, of
course) until that reference’s lifetime expires. Similarly, if you create a &mut T
reference that
is released to safe code, then you must not access the data within the [UnsafeAliasCell<T>
] until
that reference expires.UnsafeAliasCell<T>
], then any writes must have a proper happens-before relation to all other
accesses (or use atomics).Under the current rules, all types that are [!Unpin
] do not emit noalias
for &T
and &mut T
in [LLVM] and are thus able to alias. For [UnsafeAliasCell<T>
] to be sound, it is therefore
required to be contained in only [!Unpin
] types.