about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Hewson <michael@michaelhewson.ca>2018-10-03 23:40:21 -0400
committerMichael Hewson <michael@michaelhewson.ca>2018-11-01 18:16:59 -0400
commitf12c250e40650e6103161f986f02a84b7357bdc9 (patch)
treec79c2edee2f4e22e63cd3baef0b0bebd982c103d
parentc29641e067d44c754fbc6a40e463a7e4d45ab31e (diff)
downloadrust-f12c250e40650e6103161f986f02a84b7357bdc9.tar.gz
rust-f12c250e40650e6103161f986f02a84b7357bdc9.zip
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.
-rw-r--r--src/liballoc/boxed.rs6
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/liballoc/rc.rs10
-rw-r--r--src/liballoc/sync.rs10
-rw-r--r--src/libcore/nonzero.rs4
-rw-r--r--src/libcore/ops/mod.rs4
-rw-r--r--src/libcore/ops/unsize.rs48
-rw-r--r--src/libcore/pin.rs7
-rw-r--r--src/libcore/ptr.rs8
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc/traits/object_safety.rs62
-rw-r--r--src/librustc_typeck/coherence/builtin.rs34
-rw-r--r--src/librustc_typeck/diagnostics.rs51
-rw-r--r--src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs17
-rw-r--r--src/test/ui/invalid_coerce_sized_impls.stderr33
-rw-r--r--src/test/ui/invalid_dispatch_from_dyn_impls.rs (renamed from src/test/ui/invalid_coerce_sized_impls.rs)24
-rw-r--r--src/test/ui/invalid_dispatch_from_dyn_impls.stderr32
17 files changed, 164 insertions, 190 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 8a4e646f278..74354f605e5 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -77,7 +77,7 @@ use core::iter::FusedIterator;
 use core::marker::{Unpin, Unsize};
 use core::mem;
 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::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")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Box<T>> for Box<U> {}
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
 
 #[stable(feature = "box_slice_clone", since = "1.3.0")]
 impl<T: Clone> Clone for Box<[T]> {
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 93c340a6dbd..ad6e594c884 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -86,7 +86,7 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
-#![feature(coerce_sized)]
+#![feature(dispatch_from_dyn)]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index c1cc7ac976d..be452ebb45a 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -255,7 +255,7 @@ use core::marker;
 use core::marker::{Unpin, Unsize, PhantomData};
 use core::mem::{self, align_of_val, forget, size_of_val};
 use core::ops::Deref;
-use core::ops::{CoerceUnsized, CoerceSized};
+use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::convert::From;
@@ -297,8 +297,8 @@ impl<T: ?Sized> !marker::Sync for Rc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
 
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Rc<T>> for Rc<U> {}
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
 
 impl<T> 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")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Weak<T>> for Weak<U> {}
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 358e18bbe1b..d388f76d8e8 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -25,7 +25,7 @@ use core::cmp::Ordering;
 use core::intrinsics::abort;
 use core::mem::{self, align_of_val, size_of_val};
 use core::ops::Deref;
-use core::ops::{CoerceUnsized, CoerceSized};
+use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 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")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Arc<T>> for Arc<U> {}
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+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
 /// 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")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Weak<T>> for Weak<U> {}
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index 2bc6c36171c..436cd1fc057 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -10,7 +10,7 @@
 
 //! 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
 /// 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: CoerceSized<T>> CoerceSized<NonZero<T>> for NonZero<U> {}
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs
index bf9775e2ae8..edfa6df11ac 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -202,5 +202,5 @@ pub use self::generator::{Generator, GeneratorState};
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 pub use self::unsize::CoerceUnsized;
 
-#[unstable(feature = "coerce_sized", issue = "0")]
-pub use self::unsize::CoerceSized;
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+pub use self::unsize::DispatchFromDyn;
diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs
index 0112258134d..822c80fadde 100644
--- a/src/libcore/ops/unsize.rs
+++ b/src/libcore/ops/unsize.rs
@@ -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 {}
 
 
-/// Pointers to unsized types that can be coerced to a pointer to a sized type,
-/// 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.
+/// This is used for object safety, to check that a method's receiver type can be dispatched on.
 ///
-/// `CoerceSized` is implemented for:
-/// - `&[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>`
-#[unstable(feature = "coerce_sized", issue = "0")]
-#[cfg_attr(not(stage0), lang = "coerce_sized")]
-pub trait CoerceSized<T> where T: CoerceUnsized<Self> {
+/// example impl:
+///
+/// ```
+/// impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T>
+/// where
+///     T: Unsize<U>,
+/// {}
+/// ```
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[cfg_attr(not(stage0), lang = "dispatch_from_dyn")]
+pub trait DispatchFromDyn<T> {
     // Empty.
 }
 
-// &U -> &T
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<&'a T> for &'a U {}
-// &mut U -> &mut T
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<&'a mut T> for &'a mut U {}
-// *const U -> *const T
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<*const T> for *const U {}
-// *mut U -> *mut T
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<*mut T> for *mut U {}
+// &T -> &U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
+// &mut T -> &mut U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
+// *const T -> *const U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
+// *mut T -> *mut U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
 
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 87ca193aeee..68de82d2945 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -91,7 +91,7 @@
 
 use fmt;
 use marker::Sized;
-use ops::{Deref, DerefMut, CoerceUnsized, CoerceSized};
+use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};
 
 #[doc(inline)]
 pub use marker::Unpin;
@@ -325,10 +325,9 @@ where
 {}
 
 #[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
-    P: CoerceUnsized<U>,
-    U: CoerceSized<P>,
+    P: DispatchFromDyn<U>,
 {}
 
 #[unstable(feature = "pin", issue = "49150")]
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 24ef028b49d..62ccf6c865c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -75,7 +75,7 @@
 
 use convert::From;
 use intrinsics;
-use ops::{CoerceUnsized, CoerceSized};
+use ops::{CoerceUnsized, DispatchFromDyn};
 use fmt;
 use hash;
 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> { }
 
 #[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")]
 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")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
 
-#[unstable(feature = "coerce_sized", issue = "0")]
-impl<T: ?Sized, U: ?Sized> CoerceSized<NonNull<T>> for NonNull<U> where T: Unsize<U> { }
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
 
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: ?Sized> fmt::Debug for NonNull<T> {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 67864f67bfc..cce8081daf2 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -271,7 +271,7 @@ language_item_table! {
     DropTraitLangItem,           "drop",               drop_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;
     SubTraitLangItem,            "sub",                sub_trait,               Target::Trait;
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 470a5c6bc9e..5e7a3043ae7 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -319,13 +319,12 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             &sig.map_bound(|sig| sig.inputs()[0]),
         );
 
-        // until `unsized_locals` is fully implemented, `self: Self` can't be coerced from
-        // `Self=dyn Trait` to `Self=T`. However, this is already considered object-safe. We allow
-        // it as a special case here.
-        // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_coercible` allows
+        // until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
+        // However, this is already considered object-safe. We allow it as a special case here.
+        // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
         // `Receiver: Unsize<Receiver[Self => dyn Trait]>`
         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);
             }
         }
@@ -333,27 +332,29 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
         None
     }
 
-    /// checks the method's receiver (the `self` argument) can be coerced from
-    /// a fat pointer, including the trait object vtable, to a thin pointer.
-    /// e.g. from `Rc<dyn Trait>` to `Rc<T>`, where `T` is the erased type of the underlying object.
-    /// More formally:
+    /// checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
+    /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
+    /// in the following way:
     /// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`
     /// - require the following bound:
     ///       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`"
     ///   (substitution notation).
     ///
     /// some examples of receiver types and their required obligation
-    /// - `&'a mut self` requires `&'a mut dyn Trait: CoerceSized<&'a mut T>`
-    /// - `self: Rc<Self>` requires `Rc<dyn Trait>: CoerceSized<Rc<T>>`
+    /// - `&'a mut self` requires `&'a mut T: DispatchFromDyn<&'a mut dyn Trait>`
+    /// - `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.
     /// 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
-    /// needs to be coerced is behind a pointer.
+    /// is no way, or at least no inexpensive way, to coerce the receiver from the version where
+    /// `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`
     /// 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) {
     ///         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: Rc<Self>`, this means `Rc<U>: CoerceSized<Rc<Self>>`
+    /// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
+    /// 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
     // fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
     // `self: Wrapper<Self>`.
     #[allow(dead_code)]
-    fn receiver_is_coercible(
+    fn receiver_is_dispatchable(
         self,
         method: &ty::AssociatedItem,
         receiver_ty: Ty<'tcx>,
     ) -> 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(),
-                      self.lang_items().coerce_sized_trait());
-        let (unsize_did, coerce_sized_did) = if let (Some(u), Some(cu)) = traits {
+                      self.lang_items().dispatch_from_dyn_trait());
+        let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
             (u, cu)
         } else {
-            debug!("receiver_is_coercible: Missing Unsize or CoerceSized traits");
+            debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
             return false;
         };
 
         // 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
         // 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,
             Name::intern("RustaceansAreAwesome").as_interned_str(),
         );
@@ -405,7 +407,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 
             let predicate = ty::TraitRef {
                 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();
 
             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, _| {
             if param.index == 0 {
-                target_self_ty.into()
+                unsized_self_ty.into()
             } else {
                 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
         let unsized_receiver_ty = receiver_ty.subst(self, receiver_substs);
 
-        // Receiver[Self => U]: CoerceSized<Receiver>
+        // Receiver: DispatchFromDyn<Receiver[Self => U]>
         let obligation = {
             let predicate = ty::TraitRef {
-                def_id: coerce_sized_did,
-                substs: self.mk_substs_trait(unsized_receiver_ty, &[receiver_ty.into()]),
+                def_id: dispatch_from_dyn_did,
+                substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
             }.to_predicate();
 
             Obligation::new(
@@ -442,7 +444,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
         };
 
         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)
         })
     }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index eba73b1da9a..a01718bc128 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -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().copy_trait(), visit_implementation_of_copy)
         .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> {
@@ -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) {
-    debug!("visit_implementation_of_coerce_sized: impl_did={:?}",
+fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    impl_did: DefId,
+) {
+    debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}",
            impl_did);
     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 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());
         let target = {
             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)
         };
 
-        debug!("visit_implementation_of_coerce_sized: {:?} -> {:?}",
+        debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}",
             source,
             target);
 
@@ -209,7 +213,7 @@ fn visit_implementation_of_coerce_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, i
 
                         create_err(
                             &format!(
-                                "the trait `CoerceSized` may only be implemented \
+                                "the trait `DispatchFromDyn` may only be implemented \
                                 for a coercion between structures with the same \
                                 definition; expected {}, found {}",
                                 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 ok.obligations.is_empty() {
                                 create_err(
-                                    "the trait `CoerceSized` may only be implemented for structs \
-                                     containing the field being coerced, `PhantomData` fields, \
-                                     and nothing else"
+                                    "the trait `DispatchFromDyn` may only be implemented \
+                                     for structs containing the field being coerced, \
+                                     `PhantomData` fields, and nothing else"
                                 ).note(
                                     &format!(
                                         "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() {
                         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 \
                             being coerced, none found"
                         ).emit();
                     } else if coerced_fields.len() > 1 {
                         create_err(
-                            "implementing the `CoerceSized` trait requires multiple coercions",
+                            "implementing the `DispatchFromDyn` trait requires multiple coercions",
                         ).note(
-                            "the trait `CoerceSized` may only be implemented \
+                            "the trait `DispatchFromDyn` may only be implemented \
                                 for a coercion between structures with a single field \
                                 being coerced"
                         ).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(
                                 param_env,
                                 cause.clone(),
-                                coerce_sized_trait,
+                                dispatch_from_dyn_trait,
                                 0,
                                 field.ty(tcx, substs_a),
                                 &[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(
-                        "the trait `CoerceSsized` may only be implemented \
+                        "the trait `DispatchFromDyn` may only be implemented \
                         for a coercion between structures"
                     ).emit();
                 }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 2cfca345c27..e53536fc55a 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -3085,75 +3085,58 @@ struct.
 "##,
 
 E0378: r##"
-The `CoerceSized` trait currently can only be implemented for builtin pointer
-types and structs that are newtype wrappers around them — that is, the struct
-must have only one field (except for`PhantomData`), and that field must itself
-implement `CoerceSized`.
+The `DispatchFromDyn` trait currently can only be implemented for
+builtin pointer types and structs that are newtype wrappers around them
+— that is, the struct must have only one field (except for`PhantomData`),
+and that field must itself implement `DispatchFromDyn`.
 
 Examples:
 
 ```
-#![feature(coerce_sized, unsize)]
+#![feature(dispatch_from_dyn, unsize)]
 use std::{
     marker::Unsize,
-    ops::CoerceSized,
+    ops::DispatchFromDyn,
 };
 
 struct Ptr<T: ?Sized>(*const T);
 
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T>
-where
-    T: Unsize<U>,
-{}
-
-impl<T: ?Sized, U: ?Sized> CoerceSized<Ptr<T>> for Ptr<U>
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T>
 where
     T: Unsize<U>,
 {}
 ```
 
 ```
-#![feature(coerce_unsized, coerce_sized)]
-use std::ops::{CoerceUnsized, CoerceSized};
+#![feature(dispatch_from_dyn)]
+use std::ops::DispatchFromDyn;
 
 struct Wrapper<T> {
     ptr: T,
     _phantom: PhantomData<()>,
 }
 
-impl<T, U> CoerceUnsized<Wrapper<U>> for Wrapper<T>
-where
-    T: CoerceUnsized<U>,
-{}
-
-impl<T, U> CoerceSized<Wrapper<T>> for Wrapper<U>
+impl<T, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T>
 where
-    T: CoerceUnsized<U>,
-    U: CoerceSized<T>,
+    T: DispatchFromDyn<U>,
 {}
 ```
 
-Example of illegal CoerceSized implementation
+Example of illegal `DispatchFromDyn` implementation
 (illegal because of extra field)
 
 ```compile-fail,E0378
-#![feature(coerce_unsized, coerce_sized)]
-use std::ops::{CoerceUnsized, CoerceSized};
+#![feature(dispatch_from_dyn)]
+use std::ops::DispatchFromDyn;
 
-struct WrapperWithExtraField<T> {
+struct WrapperExtraField<T> {
     ptr: T,
     extra_stuff: i32,
 }
 
-impl<T, U> CoerceUnsized<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
-where
-    T: CoerceUnsized<U>,
-{}
-
-impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
+impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T>
 where
-    T: CoerceUnsized<U>,
-    U: CoerceSized<T>,
+    T: DispatchFromDyn<U>,
 {}
 ```
 "##,
diff --git a/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs b/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs
index 3abe806c9a9..e1663563cec 100644
--- a/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs
+++ b/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs
@@ -7,13 +7,12 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // 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)]
 
 use std::{
-    ops::{Deref, CoerceUnsized, CoerceSized},
+    ops::{Deref, CoerceUnsized, DispatchFromDyn},
     marker::Unsize,
-    fmt::Debug,
 };
 
 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> CoerceSized<Ptr<T>> for Ptr<U> {}
+impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<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: CoerceSized<T>> CoerceSized<Wrapper<T>> for Wrapper<U> {}
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
 
 
 trait Trait {
-    // This method can't be called on trait objects, since the receiver would be unsized,
-    // but should not cause an object safety error
+    // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable
+    // 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 ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
     fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
@@ -53,9 +53,6 @@ trait Trait {
 }
 
 impl Trait for i32 {
-    // fn wrapper(self: Wrapper<Self>) -> i32 {
-    //     *self
-    // }
     fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
         **self
     }
diff --git a/src/test/ui/invalid_coerce_sized_impls.stderr b/src/test/ui/invalid_coerce_sized_impls.stderr
deleted file mode 100644
index 70fb464d426..00000000000
--- a/src/test/ui/invalid_coerce_sized_impls.stderr
+++ /dev/null
@@ -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`.
diff --git a/src/test/ui/invalid_coerce_sized_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
index 27d65b880fa..101e1eb6e30 100644
--- a/src/test/ui/invalid_coerce_sized_impls.rs
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
@@ -8,25 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsize, coerce_sized, coerce_unsized)]
+#![feature(unsize, dispatch_from_dyn)]
 
 use std::{
-    ops::{CoerceSized, CoerceUnsized},
+    ops::DispatchFromDyn,
     marker::{Unsize, PhantomData},
 };
 
 struct WrapperWithExtraField<T>(T, i32);
 
-impl<T, U> CoerceUnsized<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
 where
-    T: CoerceUnsized<U>,
-{}
-
-impl<T, U> CoerceSized<WrapperWithExtraField<T>> for WrapperWithExtraField<U>
-where
-    T: CoerceUnsized<U>,
-    U: CoerceSized<T>,
-{} //~^^^^ ERROR [E0378]
+    T: DispatchFromDyn<U>,
+{} //~^^^ ERROR [E0378]
 
 
 struct MultiplePointers<T: ?Sized>{
@@ -34,9 +28,7 @@ struct MultiplePointers<T: ?Sized>{
     ptr2: *const T,
 }
 
-// No CoerceUnsized impl
-
-impl<T: ?Sized, U: ?Sized> CoerceSized<MultiplePointers<T>> for MultiplePointers<U>
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
 where
     T: Unsize<U>,
 {} //~^^^ ERROR [E0378]
@@ -46,9 +38,7 @@ struct NothingToCoerce<T: ?Sized> {
     data: PhantomData<T>,
 }
 
-// No CoerceUnsized impl
-
-impl<T: ?Sized, U: ?Sized> CoerceSized<NothingToCoerce<U>> for NothingToCoerce<T> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
 //~^ ERROR [E0378]
 
 fn main() {}
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
new file mode 100644
index 00000000000..5e394f2fb91
--- /dev/null
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
@@ -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`.