diff options
| author | Yuki Okushi <jtitor@2k36.org> | 2022-10-16 11:41:12 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-16 11:41:12 +0900 |
| commit | cbc0a73c951128b783ea4953844ef5beb6e9cc5a (patch) | |
| tree | 68be4b2b83e17c8c8be1d57abd3c6299c0ab3b7b /compiler/rustc_plugin_impl/src/errors.rs | |
| parent | ddc7fd983736bef0e610e02f5ef08955ecd562bb (diff) | |
| parent | ddd119b2fed57eb6b19c44c18108de95c564a48d (diff) | |
| download | rust-cbc0a73c951128b783ea4953844ef5beb6e9cc5a.tar.gz rust-cbc0a73c951128b783ea4953844ef5beb6e9cc5a.zip | |
Rollup merge of #101717 - Pointerbender:unsafecell-memory-layout, r=Amanieu
Add documentation about the memory layout of `UnsafeCell<T>`
The documentation for `UnsafeCell<T>` currently does not make any promises about its memory layout. This PR adds this documentation, namely that the memory layout of `UnsafeCell<T>` is the same as the memory layout of its inner `T`.
# Use case
Without this layout promise, the following cast would not be legally possible:
```rust
fn example<T>(ptr: *mut T) -> *const UnsafeCell<T> {
ptr as *const UnsafeCell<T>
}
```
A use case where this can come up involves FFI. If Rust receives a pointer over a FFI boundary which provides shared read-write access (with some form of custom synchronization), and this pointer is managed by some Rust struct with lifetime `'a`, then it would greatly simplify its (internal) API and safety contract if a `&'a UnsafeCell<T>` can be created from a raw FFI pointer `*mut T`. A lot of safety checks can be done when receiving the pointer for the first time through FFI (non-nullness, alignment, initialize uninit bytes, etc.) and these properties can then be encoded into the `&UnsafeCell<T>` type. Without this documentation guarantee, this is not legal today outside of the standard library.
# Caveats
Casting in the opposite direction is still not valid, even with this documentation change:
```rust
fn example2<T>(ptr: &UnsafeCell<T>) -> &mut T {
let t = ptr as *const UnsafeCell<T> as *mut T;
unsafe { &mut *t }
}
```
This is because the only legal way to obtain a mutable pointer to the contents of the shared reference is through [`UnsafeCell::get`](https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html#method.get) and [`UnsafeCell::raw_get`](https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html#method.raw_get). Although there might be a desire to also make this legal at some point in the future, that part is outside the scope of this PR. Also see this relevant [Zulip thread](https://rust-lang.zulipchat.com/#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/transmuting.20.26.20-.3E.20.26mut).
# Alternatives
Instead of adding a new documentation promise, it's also possible to add a new method to `UnsafeCell<T>` with signature `pub fn from_ptr_bikeshed(ptr: *mut T) -> *const UnsafeCell<T>` which indirectly only allows one-way casting to `*const UnsafeCell<T>`.
Diffstat (limited to 'compiler/rustc_plugin_impl/src/errors.rs')
0 files changed, 0 insertions, 0 deletions
