-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
6 changed files
with
155 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Check that even though Cell: DispatchFromDyn it remains an invalid self parameter type | ||
|
||
use std::cell::Cell; | ||
|
||
trait Trait{ | ||
fn cell(self: Cell<&Self>); //~ ERROR invalid `self` parameter type: Cell<&Self> | ||
} | ||
|
||
fn main() {} |
12 changes: 12 additions & 0 deletions
12
tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error[E0307]: invalid `self` parameter type: Cell<&Self> | ||
--> $DIR/feature-gate-dispatch-from-dyn-cell.rs:6:19 | ||
| | ||
LL | fn cell(self: Cell<&Self>); | ||
| ^^^^^^^^^^^ | ||
| | ||
= note: type of `self` must be `Self` or a type that dereferences to it | ||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0307`. |
35 changes: 35 additions & 0 deletions
35
tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Check that a self parameter type requires a DispatchFromDyn impl to be object safe | ||
|
||
#![feature(arbitrary_self_types, unsize, coerce_unsized)] | ||
|
||
use std::{ | ||
marker::Unsize, | ||
ops::{CoerceUnsized, Deref}, | ||
}; | ||
|
||
struct Ptr<T: ?Sized>(Box<T>); | ||
|
||
impl<T: ?Sized> Deref for Ptr<T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &T { | ||
&*self.0 | ||
} | ||
} | ||
|
||
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {} | ||
// Because this impl is missing the coercion below fails. | ||
// impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {} | ||
|
||
trait Trait { | ||
fn ptr(self: Ptr<Self>); | ||
} | ||
impl Trait for i32 { | ||
fn ptr(self: Ptr<Self>) {} | ||
} | ||
|
||
fn main() { | ||
Ptr(Box::new(4)) as Ptr<dyn Trait>; | ||
//~^ ERROR the trait `Trait` cannot be made into an object | ||
//~^^ ERROR the trait `Trait` cannot be made into an object | ||
} |
45 changes: 45 additions & 0 deletions
45
tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
error[E0038]: the trait `Trait` cannot be made into an object | ||
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25 | ||
| | ||
LL | fn ptr(self: Ptr<Self>); | ||
| --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` | ||
... | ||
LL | Ptr(Box::new(4)) as Ptr<dyn Trait>; | ||
| ^^^^^^^^^^^^^^ `Trait` cannot be made into an object | ||
| | ||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> | ||
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 | ||
| | ||
LL | trait Trait { | ||
| ----- this trait cannot be made into an object... | ||
LL | fn ptr(self: Ptr<Self>); | ||
| ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on | ||
|
||
error[E0038]: the trait `Trait` cannot be made into an object | ||
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5 | ||
| | ||
LL | fn ptr(self: Ptr<Self>); | ||
| --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` | ||
... | ||
LL | Ptr(Box::new(4)) as Ptr<dyn Trait>; | ||
| ^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | ||
| | ||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> | ||
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 | ||
| | ||
LL | trait Trait { | ||
| ----- this trait cannot be made into an object... | ||
LL | fn ptr(self: Ptr<Self>); | ||
| ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on | ||
note: required for `Ptr<{integer}>` to implement `CoerceUnsized<Ptr<dyn Trait>>` | ||
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:20:40 | ||
| | ||
LL | impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {} | ||
| --------- ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ | ||
| | | ||
| unsatisfied trait bound introduced here | ||
= note: required by cast to type `Ptr<dyn Trait>` | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0038`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters