diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 129213fde7491..7f109491350f0 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 Cell { #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U> CoerceUnsized> for Cell {} +// 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` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U> DispatchFromDyn> for Cell {} + impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` /// @@ -2078,6 +2088,16 @@ impl const From for UnsafeCell { #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U> CoerceUnsized> for UnsafeCell {} +// 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` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U> DispatchFromDyn> for UnsafeCell {} + /// [`UnsafeCell`], but [`Sync`]. /// /// This is just an `UnsafeCell`, except it implements `Sync` @@ -2169,6 +2189,17 @@ impl const From for SyncUnsafeCell { //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] impl, U> CoerceUnsized> for SyncUnsafeCell {} +// 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` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +//#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl, U> DispatchFromDyn> for SyncUnsafeCell {} + #[allow(unused)] fn assert_coerce_unsized( a: UnsafeCell<&i32>, diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs new file mode 100644 index 0000000000000..83366ea02b09a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs @@ -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() {} diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr new file mode 100644 index 0000000000000..ce06ce916a758 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr @@ -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: Rc`, `self: Arc`, or `self: Pin

` (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`. diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs new file mode 100644 index 0000000000000..23857cbaca85e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs @@ -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(Box); + +impl Deref for Ptr { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} +// Because this impl is missing the coercion below fails. +// impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} + +trait Trait { + fn ptr(self: Ptr); +} +impl Trait for i32 { + fn ptr(self: Ptr) {} +} + +fn main() { + Ptr(Box::new(4)) as Ptr; + //~^ ERROR the trait `Trait` cannot be made into an object + //~^^ ERROR the trait `Trait` cannot be made into an object +} diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr new file mode 100644 index 0000000000000..d81eade8e9bfb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr @@ -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); + | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` +... +LL | Ptr(Box::new(4)) as Ptr; + | ^^^^^^^^^^^^^^ `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 + --> $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); + | ^^^^^^^^^ ...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); + | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` +... +LL | Ptr(Box::new(4)) as Ptr; + | ^^^^^^^^^^^^^^^^ `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 + --> $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); + | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on +note: required for `Ptr<{integer}>` to implement `CoerceUnsized>` + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:20:40 + | +LL | impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} + | --------- ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: required by cast to type `Ptr` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs index 65fec3becacee..91aacedfc5778 100644 --- a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs +++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -3,6 +3,7 @@ #![feature(rustc_attrs)] use std::{ + cell::Cell, ops::{Deref, CoerceUnsized, DispatchFromDyn}, marker::Unsize, }; @@ -20,6 +21,20 @@ impl Deref for Ptr { impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} + +struct CellPtr<'a, T: ?Sized>(Cell<&'a T>); + +impl<'a, T: ?Sized> Deref for CellPtr<'a, T> { + type Target = T; + + fn deref(&self) -> &T { + self.0.get() + } +} + +impl<'a, T: Unsize + ?Sized, U: ?Sized> CoerceUnsized> for CellPtr<'a, T> {} +impl<'a, T: Unsize + ?Sized, U: ?Sized> DispatchFromDyn> for CellPtr<'a, T> {} + struct Wrapper(T); impl Deref for Wrapper { @@ -42,6 +57,7 @@ trait Trait { fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; + fn cell(self: CellPtr) -> i32; } impl Trait for i32 { @@ -54,6 +70,9 @@ impl Trait for i32 { fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32 { ***self } + fn cell(self: CellPtr) -> i32 { + *self + } } fn main() { @@ -65,4 +84,7 @@ fn main() { let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper>>; assert_eq!(wpw.wrapper_ptr_wrapper(), 7); + + let c = CellPtr(Cell::new(&8)) as CellPtr; + assert_eq!(c.cell(), 8); }