diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-01-26 07:53:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-26 07:53:21 +0100 |
| commit | e0d71f500cabca8f8bd1b660bbd292bf451b1bab (patch) | |
| tree | fbffdf6734cba4d9c39b9f8f727be76eef5da8f6 /library/core/src | |
| parent | 885bf628879310b885721e1fdd91ea2cbca9311f (diff) | |
| parent | af58854168f2ae6b0af89d7945584cb78e276193 (diff) | |
| download | rust-e0d71f500cabca8f8bd1b660bbd292bf451b1bab.tar.gz rust-e0d71f500cabca8f8bd1b660bbd292bf451b1bab.zip | |
Rollup merge of #97373 - dimpolo:cell_dispatch_from_dyn, r=dtolnay
impl DispatchFromDyn for Cell and UnsafeCell
After some fruitful discussion on [Internals](https://internals.rust-lang.org/t/impl-dispatchfromdyn-for-cell-2/16520) here's my first PR to rust-lang/rust 🎉
Please let me know if there's something I missed.
This adds `DispatchFromDyn` impls for `Cell`, `UnsafeCell` and `SyncUnsafeCell`.
An existing test is also expanded to test the `Cell` impl (which requires the `UnsafeCell` impl)
The different `RefCell` types can not implement `DispatchFromDyn` since they have more than one (non ZST) field.
**Edit:**
### What:
These changes allow one to make types like `MyRc`(code below), to be object safe method receivers after implementing `DispatchFromDyn` and `Deref` for them.
This allows for code like this:
```rust
struct MyRc<T: ?Sized>(Cell<NonNull<RcBox<T>>>);
/* impls for DispatchFromDyn, CoerceUnsized and Deref for MyRc*/
trait Trait {
fn foo(self: MyRc<Self>);
}
let impls_trait = ...;
let rc = MyRc::new(impls_trait) as MyRc<dyn Trait>;
rc.foo();
```
Note: `Cell` and `UnsafeCell` won't directly become valid method receivers since they don't implement `Deref`. Making use of these changes requires a wrapper type and nightly features.
### Why:
A custom pointer type with interior mutability allows one to store extra information in the pointer itself.
These changes allow for such a type to be a method receiver.
### Examples:
My use case is a cycle aware custom `Rc` implementation that when dropping a cycle marks some references dangling.
On the [forum](https://internals.rust-lang.org/t/impl-dispatchfromdyn-for-cell/14762/8) andersk mentioned that they track if a `Gc` reference is rooted with an extra bit in the reference itself.
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/cell.rs | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 129213fde74..7f109491350 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -196,7 +196,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; use crate::marker::{PhantomData, Unsize}; use crate::mem; -use crate::ops::{CoerceUnsized, Deref, DerefMut}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn}; use crate::ptr::{self, NonNull}; mod lazy; @@ -571,6 +571,16 @@ impl<T: Default> Cell<T> { #[unstable(feature = "coerce_unsized", issue = "18598")] impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {} +// Allow types that wrap `Cell` to also implement `DispatchFromDyn` +// and become object safe method receivers. +// Note that currently `Cell` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: Cell<&Self>` won't work +// `self: CellWrapper<Self>` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {} + impl<T> Cell<[T]> { /// Returns a `&[Cell<T>]` from a `&Cell<[T]>` /// @@ -2078,6 +2088,16 @@ impl<T> const From<T> for UnsafeCell<T> { #[unstable(feature = "coerce_unsized", issue = "18598")] impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {} +// Allow types that wrap `UnsafeCell` to also implement `DispatchFromDyn` +// and become object safe method receivers. +// Note that currently `UnsafeCell` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: UnsafeCell<&Self>` won't work +// `self: UnsafeCellWrapper<Self>` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {} + /// [`UnsafeCell`], but [`Sync`]. /// /// This is just an `UnsafeCell`, except it implements `Sync` @@ -2169,6 +2189,17 @@ impl<T> const From<T> for SyncUnsafeCell<T> { //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] impl<T: CoerceUnsized<U>, U> CoerceUnsized<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {} +// Allow types that wrap `SyncUnsafeCell` to also implement `DispatchFromDyn` +// and become object safe method receivers. +// Note that currently `SyncUnsafeCell` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: SyncUnsafeCell<&Self>` won't work +// `self: SyncUnsafeCellWrapper<Self>` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +//#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {} + #[allow(unused)] fn assert_coerce_unsized( a: UnsafeCell<&i32>, |
