Replace CoerceSized trait with DispatchFromDyn
Rename `CoerceSized` to `DispatchFromDyn`, and reverse the direction so that, for example, you write ``` impl<T: Unsize<U>, U> DispatchFromDyn<*const U> for *const T {} ``` instead of ``` impl<T: Unsize<U>, U> DispatchFromDyn<*const T> for *const U {} ``` this way the trait is really just a subset of `CoerceUnsized`. The checks in object_safety.rs are updated for the new trait, and some documentation and method names in there are updated for the new trait name — e.g. `receiver_is_coercible` is now called `receiver_is_dispatchable`. Since the trait now works in the opposite direction, some code had to updated here for that too. I did not update the error messages for invalid `CoerceSized` (now `DispatchFromDyn`) implementations, except to find/replace `CoerceSized` with `DispatchFromDyn`. Will ask for suggestions in the PR thread.
This commit is contained in:
parent
c29641e067
commit
f12c250e40
17 changed files with 164 additions and 190 deletions
|
@ -77,7 +77,7 @@ use core::iter::FusedIterator;
|
||||||
use core::marker::{Unpin, Unsize};
|
use core::marker::{Unpin, Unsize};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::ops::{CoerceUnsized, CoerceSized, Deref, DerefMut, Generator, GeneratorState};
|
use core::ops::{CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Generator, GeneratorState};
|
||||||
use core::ptr::{self, NonNull, Unique};
|
use core::ptr::{self, NonNull, Unique};
|
||||||
use core::task::{LocalWaker, Poll};
|
use core::task::{LocalWaker, Poll};
|
||||||
|
|
||||||
|
@ -696,8 +696,8 @@ impl<'a, A, R> FnOnce<A> for Box<dyn FnBox<A, Output = R> + Send + 'a> {
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
|
||||||
|
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Box<T>> for Box<U> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
|
||||||
|
|
||||||
#[stable(feature = "box_slice_clone", since = "1.3.0")]
|
#[stable(feature = "box_slice_clone", since = "1.3.0")]
|
||||||
impl<T: Clone> Clone for Box<[T]> {
|
impl<T: Clone> Clone for Box<[T]> {
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(cfg_target_has_atomic)]
|
#![feature(cfg_target_has_atomic)]
|
||||||
#![feature(coerce_unsized)]
|
#![feature(coerce_unsized)]
|
||||||
#![feature(coerce_sized)]
|
#![feature(dispatch_from_dyn)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(custom_attribute)]
|
#![feature(custom_attribute)]
|
||||||
#![feature(dropck_eyepatch)]
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
|
@ -255,7 +255,7 @@ use core::marker;
|
||||||
use core::marker::{Unpin, Unsize, PhantomData};
|
use core::marker::{Unpin, Unsize, PhantomData};
|
||||||
use core::mem::{self, align_of_val, forget, size_of_val};
|
use core::mem::{self, align_of_val, forget, size_of_val};
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use core::ops::{CoerceUnsized, CoerceSized};
|
use core::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::ptr::{self, NonNull};
|
use core::ptr::{self, NonNull};
|
||||||
use core::convert::From;
|
use core::convert::From;
|
||||||
|
@ -297,8 +297,8 @@ impl<T: ?Sized> !marker::Sync for Rc<T> {}
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
|
||||||
|
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Rc<T>> for Rc<U> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
|
||||||
|
|
||||||
impl<T> Rc<T> {
|
impl<T> Rc<T> {
|
||||||
/// Constructs a new `Rc<T>`.
|
/// Constructs a new `Rc<T>`.
|
||||||
|
@ -1179,8 +1179,8 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
|
||||||
|
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Weak<T>> for Weak<U> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
|
||||||
|
|
||||||
impl<T> Weak<T> {
|
impl<T> Weak<T> {
|
||||||
/// Constructs a new `Weak<T>`, without allocating any memory.
|
/// Constructs a new `Weak<T>`, without allocating any memory.
|
||||||
|
|
|
@ -25,7 +25,7 @@ use core::cmp::Ordering;
|
||||||
use core::intrinsics::abort;
|
use core::intrinsics::abort;
|
||||||
use core::mem::{self, align_of_val, size_of_val};
|
use core::mem::{self, align_of_val, size_of_val};
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use core::ops::{CoerceUnsized, CoerceSized};
|
use core::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::ptr::{self, NonNull};
|
use core::ptr::{self, NonNull};
|
||||||
use core::marker::{Unpin, Unsize, PhantomData};
|
use core::marker::{Unpin, Unsize, PhantomData};
|
||||||
|
@ -214,8 +214,8 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
|
||||||
|
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Arc<T>> for Arc<U> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
|
||||||
|
|
||||||
/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
|
/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
|
||||||
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
|
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
|
||||||
|
@ -257,8 +257,8 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}
|
||||||
|
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Weak<T>> for Weak<U> {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
|
||||||
|
|
||||||
#[stable(feature = "arc_weak", since = "1.4.0")]
|
#[stable(feature = "arc_weak", since = "1.4.0")]
|
||||||
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
|
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
//! Exposes the NonZero lang item which provides optimization hints.
|
//! Exposes the NonZero lang item which provides optimization hints.
|
||||||
|
|
||||||
use ops::{CoerceUnsized, CoerceSized};
|
use ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
|
|
||||||
/// A wrapper type for raw pointers and integers that will never be
|
/// A wrapper type for raw pointers and integers that will never be
|
||||||
/// NULL or 0 that might allow certain optimizations.
|
/// NULL or 0 that might allow certain optimizations.
|
||||||
|
@ -21,4 +21,4 @@ pub(crate) struct NonZero<T>(pub(crate) T);
|
||||||
|
|
||||||
impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}
|
impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}
|
||||||
|
|
||||||
impl<T: CoerceUnsized<U>, U: CoerceSized<T>> CoerceSized<NonZero<T>> for NonZero<U> {}
|
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
|
||||||
|
|
|
@ -202,5 +202,5 @@ pub use self::generator::{Generator, GeneratorState};
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
pub use self::unsize::CoerceUnsized;
|
pub use self::unsize::CoerceUnsized;
|
||||||
|
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
pub use self::unsize::CoerceSized;
|
pub use self::unsize::DispatchFromDyn;
|
||||||
|
|
|
@ -79,32 +79,32 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
|
||||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||||
|
|
||||||
|
|
||||||
/// Pointers to unsized types that can be coerced to a pointer to a sized type,
|
/// This is used for object safety, to check that a method's receiver type can be dispatched on.
|
||||||
/// as long as pointee is actually a value of that sized type. This is used for
|
|
||||||
/// object safety, to check that a method's receiver type can be coerced from the version
|
|
||||||
/// where `Self = dyn Trait` to the version where `Self = T`, the erased, sized type
|
|
||||||
/// of the underlying object.
|
|
||||||
///
|
///
|
||||||
/// `CoerceSized` is implemented for:
|
/// example impl:
|
||||||
/// - `&[T]` is `CoerceSized<&[T; N]>` for any `N`
|
///
|
||||||
/// - `&Trait` is `CoerceSized<&T>` for any `T: Trait`
|
/// ```
|
||||||
/// - and similarly for `&mut T`, `*const T`, `*mut T`, `Box<T>`, `Rc<T>`, `Arc<T>`
|
/// impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T>
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
/// where
|
||||||
#[cfg_attr(not(stage0), lang = "coerce_sized")]
|
/// T: Unsize<U>,
|
||||||
pub trait CoerceSized<T> where T: CoerceUnsized<Self> {
|
/// {}
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
|
#[cfg_attr(not(stage0), lang = "dispatch_from_dyn")]
|
||||||
|
pub trait DispatchFromDyn<T> {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
// &U -> &T
|
// &T -> &U
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<&'a T> for &'a U {}
|
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||||
// &mut U -> &mut T
|
// &mut T -> &mut U
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<&'a mut T> for &'a mut U {}
|
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||||
// *const U -> *const T
|
// *const T -> *const U
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<*const T> for *const U {}
|
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||||
// *mut U -> *mut T
|
// *mut T -> *mut U
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<*mut T> for *mut U {}
|
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
|
|
||||||
use fmt;
|
use fmt;
|
||||||
use marker::Sized;
|
use marker::Sized;
|
||||||
use ops::{Deref, DerefMut, CoerceUnsized, CoerceSized};
|
use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use marker::Unpin;
|
pub use marker::Unpin;
|
||||||
|
@ -325,10 +325,9 @@ where
|
||||||
{}
|
{}
|
||||||
|
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
impl<'a, P, U> CoerceSized<Pin<P>> for Pin<U>
|
impl<'a, P, U> DispatchFromDyn<Pin<U>> for Pin<P>
|
||||||
where
|
where
|
||||||
P: CoerceUnsized<U>,
|
P: DispatchFromDyn<U>,
|
||||||
U: CoerceSized<P>,
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
|
|
||||||
use convert::From;
|
use convert::From;
|
||||||
use intrinsics;
|
use intrinsics;
|
||||||
use ops::{CoerceUnsized, CoerceSized};
|
use ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
use fmt;
|
use fmt;
|
||||||
use hash;
|
use hash;
|
||||||
use marker::{PhantomData, Unsize};
|
use marker::{PhantomData, Unsize};
|
||||||
|
@ -2796,7 +2796,7 @@ impl<T: ?Sized> Copy for Unique<T> { }
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceSized<Unique<T>> for Unique<U> where T: Unsize<U> { }
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
impl<T: ?Sized> fmt::Pointer for Unique<T> {
|
impl<T: ?Sized> fmt::Pointer for Unique<T> {
|
||||||
|
@ -2954,8 +2954,8 @@ impl<T: ?Sized> Copy for NonNull<T> { }
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
#[unstable(feature = "coerce_sized", issue = "0")]
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceSized<NonNull<T>> for NonNull<U> where T: Unsize<U> { }
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
||||||
|
|
|
@ -271,7 +271,7 @@ language_item_table! {
|
||||||
DropTraitLangItem, "drop", drop_trait, Target::Trait;
|
DropTraitLangItem, "drop", drop_trait, Target::Trait;
|
||||||
|
|
||||||
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait;
|
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait;
|
||||||
CoerceSizedTraitLangItem, "coerce_sized", coerce_sized_trait, Target::Trait;
|
DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait;
|
||||||
|
|
||||||
AddTraitLangItem, "add", add_trait, Target::Trait;
|
AddTraitLangItem, "add", add_trait, Target::Trait;
|
||||||
SubTraitLangItem, "sub", sub_trait, Target::Trait;
|
SubTraitLangItem, "sub", sub_trait, Target::Trait;
|
||||||
|
|
|
@ -319,13 +319,12 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
&sig.map_bound(|sig| sig.inputs()[0]),
|
&sig.map_bound(|sig| sig.inputs()[0]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// until `unsized_locals` is fully implemented, `self: Self` can't be coerced from
|
// until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
|
||||||
// `Self=dyn Trait` to `Self=T`. However, this is already considered object-safe. We allow
|
// However, this is already considered object-safe. We allow it as a special case here.
|
||||||
// it as a special case here.
|
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
|
||||||
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_coercible` allows
|
|
||||||
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
|
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
|
||||||
if receiver_ty != self.mk_self_type() {
|
if receiver_ty != self.mk_self_type() {
|
||||||
if !self.receiver_is_coercible(method, receiver_ty) {
|
if !self.receiver_is_dispatchable(method, receiver_ty) {
|
||||||
return Some(MethodViolationCode::UncoercibleReceiver);
|
return Some(MethodViolationCode::UncoercibleReceiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,27 +332,29 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// checks the method's receiver (the `self` argument) can be coerced from
|
/// checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
|
||||||
/// a fat pointer, including the trait object vtable, to a thin pointer.
|
/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
|
||||||
/// e.g. from `Rc<dyn Trait>` to `Rc<T>`, where `T` is the erased type of the underlying object.
|
/// in the following way:
|
||||||
/// More formally:
|
|
||||||
/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`
|
/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`
|
||||||
/// - require the following bound:
|
/// - require the following bound:
|
||||||
/// forall(T: Trait) {
|
/// forall(T: Trait) {
|
||||||
/// Receiver[Self => dyn Trait]: CoerceSized<Receiver[Self => T]>
|
/// Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
|
||||||
/// }
|
/// }
|
||||||
/// where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
|
/// where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
|
||||||
/// (substitution notation).
|
/// (substitution notation).
|
||||||
///
|
///
|
||||||
/// some examples of receiver types and their required obligation
|
/// some examples of receiver types and their required obligation
|
||||||
/// - `&'a mut self` requires `&'a mut dyn Trait: CoerceSized<&'a mut T>`
|
/// - `&'a mut self` requires `&'a mut T: DispatchFromDyn<&'a mut dyn Trait>`
|
||||||
/// - `self: Rc<Self>` requires `Rc<dyn Trait>: CoerceSized<Rc<T>>`
|
/// - `self: Rc<Self>` requires `Rc<T>: DispatchFromDyn<Rc<dyn Trait>>`
|
||||||
|
/// - `self: Pin<Box<Self>>` requires `Pin<Box<T>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`
|
||||||
///
|
///
|
||||||
/// The only case where the receiver is not coercible, but is still a valid receiver
|
/// The only case where the receiver is not dispatchable, but is still a valid receiver
|
||||||
/// type (just not object-safe), is when there is more than one level of pointer indirection.
|
/// type (just not object-safe), is when there is more than one level of pointer indirection.
|
||||||
/// e.g. `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
|
/// e.g. `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
|
||||||
/// is no way, or at least no inexpensive way, to coerce the receiver, because the object that
|
/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
|
||||||
/// needs to be coerced is behind a pointer.
|
/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
|
||||||
|
/// contained by the trait object, because the object that needs to be coerced is behind
|
||||||
|
/// a pointer.
|
||||||
///
|
///
|
||||||
/// In practice, there are issues with the above bound: `where` clauses that apply to `Self`
|
/// In practice, there are issues with the above bound: `where` clauses that apply to `Self`
|
||||||
/// would have to apply to `T`, trait object types have a lot of parameters that need to
|
/// would have to apply to `T`, trait object types have a lot of parameters that need to
|
||||||
|
@ -364,37 +365,38 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
///
|
///
|
||||||
/// forall (U: ?Sized) {
|
/// forall (U: ?Sized) {
|
||||||
/// if (Self: Unsize<U>) {
|
/// if (Self: Unsize<U>) {
|
||||||
/// Receiver[Self => U]: CoerceSized<Receiver>
|
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// for `self: &'a mut Self`, this means `&'a mut U: CoerceSized<&'a mut Self>`
|
/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
|
||||||
/// for `self: Rc<Self>`, this means `Rc<U>: CoerceSized<Rc<Self>>`
|
/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
|
||||||
|
/// for `self: Pin<Box<Self>>, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
|
||||||
//
|
//
|
||||||
// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
|
// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
|
||||||
// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
|
// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
|
||||||
// `self: Wrapper<Self>`.
|
// `self: Wrapper<Self>`.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn receiver_is_coercible(
|
fn receiver_is_dispatchable(
|
||||||
self,
|
self,
|
||||||
method: &ty::AssociatedItem,
|
method: &ty::AssociatedItem,
|
||||||
receiver_ty: Ty<'tcx>,
|
receiver_ty: Ty<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!("receiver_is_coercible: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
|
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
|
||||||
|
|
||||||
let traits = (self.lang_items().unsize_trait(),
|
let traits = (self.lang_items().unsize_trait(),
|
||||||
self.lang_items().coerce_sized_trait());
|
self.lang_items().dispatch_from_dyn_trait());
|
||||||
let (unsize_did, coerce_sized_did) = if let (Some(u), Some(cu)) = traits {
|
let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
|
||||||
(u, cu)
|
(u, cu)
|
||||||
} else {
|
} else {
|
||||||
debug!("receiver_is_coercible: Missing Unsize or CoerceSized traits");
|
debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
|
// use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
|
||||||
// FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries
|
// FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries
|
||||||
// are implemented
|
// are implemented
|
||||||
let target_self_ty: Ty<'tcx> = self.mk_ty_param(
|
let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
|
||||||
::std::u32::MAX,
|
::std::u32::MAX,
|
||||||
Name::intern("RustaceansAreAwesome").as_interned_str(),
|
Name::intern("RustaceansAreAwesome").as_interned_str(),
|
||||||
);
|
);
|
||||||
|
@ -405,7 +407,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
|
|
||||||
let predicate = ty::TraitRef {
|
let predicate = ty::TraitRef {
|
||||||
def_id: unsize_did,
|
def_id: unsize_did,
|
||||||
substs: self.mk_substs_trait(self.mk_self_type(), &[target_self_ty.into()]),
|
substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
|
||||||
}.to_predicate();
|
}.to_predicate();
|
||||||
|
|
||||||
let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter().cloned()
|
let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter().cloned()
|
||||||
|
@ -419,7 +421,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
|
|
||||||
let receiver_substs = Substs::for_item(self, method.def_id, |param, _| {
|
let receiver_substs = Substs::for_item(self, method.def_id, |param, _| {
|
||||||
if param.index == 0 {
|
if param.index == 0 {
|
||||||
target_self_ty.into()
|
unsized_self_ty.into()
|
||||||
} else {
|
} else {
|
||||||
self.mk_param_from_def(param)
|
self.mk_param_from_def(param)
|
||||||
}
|
}
|
||||||
|
@ -427,11 +429,11 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
// the type `Receiver[Self => U]` in the query
|
// the type `Receiver[Self => U]` in the query
|
||||||
let unsized_receiver_ty = receiver_ty.subst(self, receiver_substs);
|
let unsized_receiver_ty = receiver_ty.subst(self, receiver_substs);
|
||||||
|
|
||||||
// Receiver[Self => U]: CoerceSized<Receiver>
|
// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||||
let obligation = {
|
let obligation = {
|
||||||
let predicate = ty::TraitRef {
|
let predicate = ty::TraitRef {
|
||||||
def_id: coerce_sized_did,
|
def_id: dispatch_from_dyn_did,
|
||||||
substs: self.mk_substs_trait(unsized_receiver_ty, &[receiver_ty.into()]),
|
substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
|
||||||
}.to_predicate();
|
}.to_predicate();
|
||||||
|
|
||||||
Obligation::new(
|
Obligation::new(
|
||||||
|
@ -442,7 +444,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.infer_ctxt().enter(|ref infcx| {
|
self.infer_ctxt().enter(|ref infcx| {
|
||||||
// the receiver is coercible iff the obligation holds
|
// the receiver is dispatchable iff the obligation holds
|
||||||
infcx.predicate_must_hold(&obligation)
|
infcx.predicate_must_hold(&obligation)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
|
||||||
.check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
|
.check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
|
||||||
.check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
|
.check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
|
||||||
.check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
|
.check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
|
||||||
.check(tcx.lang_items().coerce_sized_trait(), visit_implementation_of_coerce_sized);
|
.check(tcx.lang_items().dispatch_from_dyn_trait(),
|
||||||
|
visit_implementation_of_dispatch_from_dyn);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Checker<'a, 'tcx: 'a> {
|
struct Checker<'a, 'tcx: 'a> {
|
||||||
|
@ -162,11 +163,14 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) {
|
fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
|
||||||
debug!("visit_implementation_of_coerce_sized: impl_did={:?}",
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
impl_did: DefId,
|
||||||
|
) {
|
||||||
|
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}",
|
||||||
impl_did);
|
impl_did);
|
||||||
if impl_did.is_local() {
|
if impl_did.is_local() {
|
||||||
let coerce_sized_trait = tcx.lang_items().coerce_sized_trait().unwrap();
|
let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap();
|
||||||
|
|
||||||
let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap();
|
let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap();
|
||||||
let span = tcx.hir.span(impl_node_id);
|
let span = tcx.hir.span(impl_node_id);
|
||||||
|
@ -175,12 +179,12 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
|
||||||
assert!(!source.has_escaping_regions());
|
assert!(!source.has_escaping_regions());
|
||||||
let target = {
|
let target = {
|
||||||
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
|
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
|
||||||
assert_eq!(trait_ref.def_id, coerce_sized_trait);
|
assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
|
||||||
|
|
||||||
trait_ref.substs.type_at(1)
|
trait_ref.substs.type_at(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("visit_implementation_of_coerce_sized: {:?} -> {:?}",
|
debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}",
|
||||||
source,
|
source,
|
||||||
target);
|
target);
|
||||||
|
|
||||||
|
@ -209,7 +213,7 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
|
||||||
|
|
||||||
create_err(
|
create_err(
|
||||||
&format!(
|
&format!(
|
||||||
"the trait `CoerceSized` may only be implemented \
|
"the trait `DispatchFromDyn` may only be implemented \
|
||||||
for a coercion between structures with the same \
|
for a coercion between structures with the same \
|
||||||
definition; expected {}, found {}",
|
definition; expected {}, found {}",
|
||||||
source_path, target_path,
|
source_path, target_path,
|
||||||
|
@ -232,9 +236,9 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
|
||||||
if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
|
if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
|
||||||
if ok.obligations.is_empty() {
|
if ok.obligations.is_empty() {
|
||||||
create_err(
|
create_err(
|
||||||
"the trait `CoerceSized` may only be implemented for structs \
|
"the trait `DispatchFromDyn` may only be implemented \
|
||||||
containing the field being coerced, `PhantomData` fields, \
|
for structs containing the field being coerced, \
|
||||||
and nothing else"
|
`PhantomData` fields, and nothing else"
|
||||||
).note(
|
).note(
|
||||||
&format!(
|
&format!(
|
||||||
"extra field `{}` of type `{}` is not allowed",
|
"extra field `{}` of type `{}` is not allowed",
|
||||||
|
@ -251,15 +255,15 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
|
||||||
|
|
||||||
if coerced_fields.is_empty() {
|
if coerced_fields.is_empty() {
|
||||||
create_err(
|
create_err(
|
||||||
"the trait `CoerceSized` may only be implemented \
|
"the trait `DispatchFromDyn` may only be implemented \
|
||||||
for a coercion between structures with a single field \
|
for a coercion between structures with a single field \
|
||||||
being coerced, none found"
|
being coerced, none found"
|
||||||
).emit();
|
).emit();
|
||||||
} else if coerced_fields.len() > 1 {
|
} else if coerced_fields.len() > 1 {
|
||||||
create_err(
|
create_err(
|
||||||
"implementing the `CoerceSized` trait requires multiple coercions",
|
"implementing the `DispatchFromDyn` trait requires multiple coercions",
|
||||||
).note(
|
).note(
|
||||||
"the trait `CoerceSized` may only be implemented \
|
"the trait `DispatchFromDyn` may only be implemented \
|
||||||
for a coercion between structures with a single field \
|
for a coercion between structures with a single field \
|
||||||
being coerced"
|
being coerced"
|
||||||
).note(
|
).note(
|
||||||
|
@ -284,7 +288,7 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
|
||||||
let predicate = tcx.predicate_for_trait_def(
|
let predicate = tcx.predicate_for_trait_def(
|
||||||
param_env,
|
param_env,
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
coerce_sized_trait,
|
dispatch_from_dyn_trait,
|
||||||
0,
|
0,
|
||||||
field.ty(tcx, substs_a),
|
field.ty(tcx, substs_a),
|
||||||
&[field.ty(tcx, substs_b).into()]
|
&[field.ty(tcx, substs_b).into()]
|
||||||
|
@ -311,7 +315,7 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
create_err(
|
create_err(
|
||||||
"the trait `CoerceSsized` may only be implemented \
|
"the trait `DispatchFromDyn` may only be implemented \
|
||||||
for a coercion between structures"
|
for a coercion between structures"
|
||||||
).emit();
|
).emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3085,75 +3085,58 @@ struct.
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0378: r##"
|
E0378: r##"
|
||||||
The `CoerceSized` trait currently can only be implemented for builtin pointer
|
The `DispatchFromDyn` trait currently can only be implemented for
|
||||||
types and structs that are newtype wrappers around them — that is, the struct
|
builtin pointer types and structs that are newtype wrappers around them
|
||||||
must have only one field (except for`PhantomData`), and that field must itself
|
— that is, the struct must have only one field (except for`PhantomData`),
|
||||||
implement `CoerceSized`.
|
and that field must itself implement `DispatchFromDyn`.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
```
|
```
|
||||||
#![feature(coerce_sized, unsize)]
|
#![feature(dispatch_from_dyn, unsize)]
|
||||||
use std::{
|
use std::{
|
||||||
marker::Unsize,
|
marker::Unsize,
|
||||||
ops::CoerceSized,
|
ops::DispatchFromDyn,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ptr<T: ?Sized>(*const T);
|
struct Ptr<T: ?Sized>(*const T);
|
||||||
|
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T>
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T>
|
||||||
where
|
|
||||||
T: Unsize<U>,
|
|
||||||
{}
|
|
||||||
|
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceSized<Ptr<T>> for Ptr<U>
|
|
||||||
where
|
where
|
||||||
T: Unsize<U>,
|
T: Unsize<U>,
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
#![feature(coerce_unsized, coerce_sized)]
|
#![feature(dispatch_from_dyn)]
|
||||||
use std::ops::{CoerceUnsized, CoerceSized};
|
use std::ops::DispatchFromDyn;
|
||||||
|
|
||||||
struct Wrapper<T> {
|
struct Wrapper<T> {
|
||||||
ptr: T,
|
ptr: T,
|
||||||
_phantom: PhantomData<()>,
|
_phantom: PhantomData<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> CoerceUnsized<Wrapper<U>> for Wrapper<T>
|
impl<T, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T>
|
||||||
where
|
where
|
||||||
T: CoerceUnsized<U>,
|
T: DispatchFromDyn<U>,
|
||||||
{}
|
|
||||||
|
|
||||||
impl<T, U> CoerceSized<Wrapper<T>> for Wrapper<U>
|
|
||||||
where
|
|
||||||
T: CoerceUnsized<U>,
|
|
||||||
U: CoerceSized<T>,
|
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
Example of illegal CoerceSized implementation
|
Example of illegal `DispatchFromDyn` implementation
|
||||||
(illegal because of extra field)
|
(illegal because of extra field)
|
||||||
|
|
||||||
```compile-fail,E0378
|
```compile-fail,E0378
|
||||||
#![feature(coerce_unsized, coerce_sized)]
|
#![feature(dispatch_from_dyn)]
|
||||||
use std::ops::{CoerceUnsized, CoerceSized};
|
use std::ops::DispatchFromDyn;
|
||||||
|
|
||||||
struct WrapperWithExtraField<T> {
|
struct WrapperExtraField<T> {
|
||||||
ptr: T,
|
ptr: T,
|
||||||
extra_stuff: i32,
|
extra_stuff: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> CoerceUnsized<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
|
impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T>
|
||||||
where
|
where
|
||||||
T: CoerceUnsized<U>,
|
T: DispatchFromDyn<U>,
|
||||||
{}
|
|
||||||
|
|
||||||
impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
|
|
||||||
where
|
|
||||||
T: CoerceUnsized<U>,
|
|
||||||
U: CoerceSized<T>,
|
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
|
@ -7,13 +7,12 @@
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
#![feature(arbitrary_self_types, unsize, coerce_unsized, coerce_sized)]
|
#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
ops::{Deref, CoerceUnsized, CoerceSized},
|
ops::{Deref, CoerceUnsized, DispatchFromDyn},
|
||||||
marker::Unsize,
|
marker::Unsize,
|
||||||
fmt::Debug,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ptr<T: ?Sized>(Box<T>);
|
struct Ptr<T: ?Sized>(Box<T>);
|
||||||
|
@ -27,7 +26,7 @@ impl<T: ?Sized> Deref for Ptr<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
|
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
|
||||||
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceSized<Ptr<T>> for Ptr<U> {}
|
impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
|
||||||
|
|
||||||
struct Wrapper<T: ?Sized>(T);
|
struct Wrapper<T: ?Sized>(T);
|
||||||
|
|
||||||
|
@ -40,12 +39,13 @@ impl<T: ?Sized> Deref for Wrapper<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
|
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
|
||||||
impl<T: CoerceUnsized<U>, U: CoerceSized<T>> CoerceSized<Wrapper<T>> for Wrapper<U> {}
|
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
|
||||||
|
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
// This method can't be called on trait objects, since the receiver would be unsized,
|
// This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable
|
||||||
// but should not cause an object safety error
|
// without unsized_locals), but wrappers arond `Self` currently are not.
|
||||||
|
// FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented
|
||||||
// fn wrapper(self: Wrapper<Self>) -> i32;
|
// fn wrapper(self: Wrapper<Self>) -> i32;
|
||||||
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
|
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
|
||||||
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
|
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
|
||||||
|
@ -53,9 +53,6 @@ trait Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for i32 {
|
impl Trait for i32 {
|
||||||
// fn wrapper(self: Wrapper<Self>) -> i32 {
|
|
||||||
// *self
|
|
||||||
// }
|
|
||||||
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
|
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
|
||||||
**self
|
**self
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
error[E0378]: the trait `CoerceSized` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
|
|
||||||
--> $DIR/invalid_coerce_sized_impls.rs:25:1
|
|
||||||
|
|
|
||||||
LL | / impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
|
|
||||||
LL | | where
|
|
||||||
LL | | T: CoerceUnsized<U>,
|
|
||||||
LL | | U: CoerceSized<T>,
|
|
||||||
LL | | {} //~^^^^ ERROR [E0378]
|
|
||||||
| |__^
|
|
||||||
|
|
|
||||||
= note: extra field `1` of type `i32` is not allowed
|
|
||||||
|
|
||||||
error[E0378]: implementing the `CoerceSized` trait requires multiple coercions
|
|
||||||
--> $DIR/invalid_coerce_sized_impls.rs:39:1
|
|
||||||
|
|
|
||||||
LL | / impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
|
|
||||||
LL | | where
|
|
||||||
LL | | T: Unsize<U>,
|
|
||||||
LL | | {} //~^^^ ERROR [E0378]
|
|
||||||
| |__^
|
|
||||||
|
|
|
||||||
= note: the trait `CoerceSized` may only be implemented for a coercion between structures with a single field being coerced
|
|
||||||
= note: currently, 2 fields need coercions: ptr1 (*const U to *const T), ptr2 (*const U to *const T)
|
|
||||||
|
|
||||||
error[E0378]: the trait `CoerceSized` may only be implemented for a coercion between structures with a single field being coerced, none found
|
|
||||||
--> $DIR/invalid_coerce_sized_impls.rs:51:1
|
|
||||||
|
|
|
||||||
LL | impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0378`.
|
|
|
@ -8,25 +8,19 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(unsize, coerce_sized, coerce_unsized)]
|
#![feature(unsize, dispatch_from_dyn)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
ops::{CoerceSized, CoerceUnsized},
|
ops::DispatchFromDyn,
|
||||||
marker::{Unsize, PhantomData},
|
marker::{Unsize, PhantomData},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WrapperWithExtraField<T>(T, i32);
|
struct WrapperWithExtraField<T>(T, i32);
|
||||||
|
|
||||||
impl<T, U> CoerceUnsized<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
|
impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
|
||||||
where
|
where
|
||||||
T: CoerceUnsized<U>,
|
T: DispatchFromDyn<U>,
|
||||||
{}
|
{} //~^^^ ERROR [E0378]
|
||||||
|
|
||||||
impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
|
|
||||||
where
|
|
||||||
T: CoerceUnsized<U>,
|
|
||||||
U: CoerceSized<T>,
|
|
||||||
{} //~^^^^ ERROR [E0378]
|
|
||||||
|
|
||||||
|
|
||||||
struct MultiplePointers<T: ?Sized>{
|
struct MultiplePointers<T: ?Sized>{
|
||||||
|
@ -34,9 +28,7 @@ struct MultiplePointers<T: ?Sized>{
|
||||||
ptr2: *const T,
|
ptr2: *const T,
|
||||||
}
|
}
|
||||||
|
|
||||||
// No CoerceUnsized impl
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
|
||||||
|
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
|
|
||||||
where
|
where
|
||||||
T: Unsize<U>,
|
T: Unsize<U>,
|
||||||
{} //~^^^ ERROR [E0378]
|
{} //~^^^ ERROR [E0378]
|
||||||
|
@ -46,9 +38,7 @@ struct NothingToCoerce<T: ?Sized> {
|
||||||
data: PhantomData<T>,
|
data: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// No CoerceUnsized impl
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
|
||||||
|
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
|
|
||||||
//~^ ERROR [E0378]
|
//~^ ERROR [E0378]
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
32
src/test/ui/invalid_dispatch_from_dyn_impls.stderr
Normal file
32
src/test/ui/invalid_dispatch_from_dyn_impls.stderr
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
|
||||||
|
--> $DIR/invalid_dispatch_from_dyn_impls.rs:20:1
|
||||||
|
|
|
||||||
|
LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
|
||||||
|
LL | | where
|
||||||
|
LL | | T: DispatchFromDyn<U>,
|
||||||
|
LL | | {} //~^^^ ERROR [E0378]
|
||||||
|
| |__^
|
||||||
|
|
|
||||||
|
= note: extra field `1` of type `i32` is not allowed
|
||||||
|
|
||||||
|
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||||
|
--> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1
|
||||||
|
|
|
||||||
|
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
|
||||||
|
LL | | where
|
||||||
|
LL | | T: Unsize<U>,
|
||||||
|
LL | | {} //~^^^ ERROR [E0378]
|
||||||
|
| |__^
|
||||||
|
|
|
||||||
|
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
|
||||||
|
= note: currently, 2 fields need coercions: ptr1 (*const T to *const U), ptr2 (*const T to *const U)
|
||||||
|
|
||||||
|
error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found
|
||||||
|
--> $DIR/invalid_dispatch_from_dyn_impls.rs:41:1
|
||||||
|
|
|
||||||
|
LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0378`.
|
Loading…
Add table
Add a link
Reference in a new issue