about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liballoc/boxed.rs5
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs8
-rw-r--r--src/liballoc/sync.rs7
-rw-r--r--src/libcore/nonzero.rs4
-rw-r--r--src/libcore/ops/mod.rs3
-rw-r--r--src/libcore/ops/unsize.rs36
-rw-r--r--src/libcore/pin.rs8
-rw-r--r--src/libcore/ptr.rs8
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc/traits/error_reporting.rs5
-rw-r--r--src/librustc/traits/object_safety.rs281
-rw-r--r--src/librustc/traits/select.rs12
-rw-r--r--src/librustc_codegen_llvm/abi.rs54
-rw-r--r--src/librustc_codegen_llvm/mir/block.rs44
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/coherence/builtin.rs177
-rw-r--r--src/librustc_typeck/diagnostics.rs60
-rw-r--r--src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs76
-rw-r--r--src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs56
-rw-r--r--src/test/ui/arbitrary-self-types-not-object-safe.rs20
-rw-r--r--src/test/ui/arbitrary-self-types-not-object-safe.stderr16
-rw-r--r--src/test/ui/error-codes/E0375.stderr2
-rw-r--r--src/test/ui/invalid_dispatch_from_dyn_impls.rs52
-rw-r--r--src/test/ui/invalid_dispatch_from_dyn_impls.stderr41
-rw-r--r--src/test/ui/issues/issue-26905.stderr2
-rw-r--r--src/test/ui/traits/trait-item-privacy.rs2
-rw-r--r--src/test/ui/traits/trait-item-privacy.stderr38
-rw-r--r--src/test/ui/traits/trait-test-2.rs1
-rw-r--r--src/test/ui/traits/trait-test-2.stderr10
30 files changed, 904 insertions, 128 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index f989e701913..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, 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,6 +696,9 @@ 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 = "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]> {
     fn clone(&self) -> Self {
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 7db6261a01c..ad6e594c884 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -86,6 +86,7 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
+#![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 3e8dfd105de..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;
+use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::convert::From;
@@ -297,6 +297,9 @@ 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 = "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>`.
     ///
@@ -1176,6 +1179,9 @@ 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 = "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.
     /// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`].
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index bcf5212f1ff..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;
+use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::marker::{Unpin, Unsize, PhantomData};
@@ -214,6 +214,9 @@ 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 = "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`
 /// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
@@ -254,6 +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 = "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 118e75e1ee7..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;
+use ops::{CoerceUnsized, DispatchFromDyn};
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
@@ -20,3 +20,5 @@ use ops::CoerceUnsized;
 pub(crate) struct NonZero<T>(pub(crate) T);
 
 impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}
+
+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 ce4f45762de..edfa6df11ac 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -201,3 +201,6 @@ pub use self::generator::{Generator, GeneratorState};
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 pub use self::unsize::CoerceUnsized;
+
+#[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 da72f374842..4d9a40a1b90 100644
--- a/src/libcore/ops/unsize.rs
+++ b/src/libcore/ops/unsize.rs
@@ -43,7 +43,7 @@ use marker::Unsize;
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 #[lang = "coerce_unsized"]
-pub trait CoerceUnsized<T> {
+pub trait CoerceUnsized<T: ?Sized> {
     // Empty.
 }
 
@@ -77,3 +77,37 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
 // *const T -> *const U
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
+
+
+/// This is used for object safety, to check that a method's receiver type can be dispatched on.
+///
+/// example impl:
+///
+/// ```
+/// # #![feature(dispatch_from_dyn, unsize)]
+/// # use std::{ops::DispatchFromDyn, marker::Unsize};
+/// # struct Rc<T: ?Sized>(::std::rc::Rc<T>);
+/// 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.
+}
+
+// &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 a03c080fb3f..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};
+use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};
 
 #[doc(inline)]
 pub use marker::Unpin;
@@ -325,4 +325,10 @@ where
 {}
 
 #[unstable(feature = "pin", issue = "49150")]
+impl<'a, P, U> DispatchFromDyn<Pin<U>> for Pin<P>
+where
+    P: DispatchFromDyn<U>,
+{}
+
+#[unstable(feature = "pin", issue = "49150")]
 impl<P> Unpin for Pin<P> {}
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 36852b10fac..62ccf6c865c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -75,7 +75,7 @@
 
 use convert::From;
 use intrinsics;
-use ops::CoerceUnsized;
+use ops::{CoerceUnsized, DispatchFromDyn};
 use fmt;
 use hash;
 use marker::{PhantomData, Unsize};
@@ -2796,6 +2796,9 @@ 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> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
+
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> fmt::Pointer for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
@@ -2951,6 +2954,9 @@ 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 = "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> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 45de958e72e..cce8081daf2 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -271,6 +271,7 @@ language_item_table! {
     DropTraitLangItem,           "drop",               drop_trait,              Target::Trait;
 
     CoerceUnsizedTraitLangItem,  "coerce_unsized",     coerce_unsized_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/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b463faef192..18ee98c515f 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -754,7 +754,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     }
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
+                        let violations = self.tcx.global_tcx()
+                            .object_safety_violations(trait_def_id);
                         self.tcx.report_object_safety_error(span,
                                                             trait_def_id,
                                                             violations)
@@ -875,7 +876,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             }
 
             TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
+                let violations = self.tcx.global_tcx().object_safety_violations(did);
                 self.tcx.report_object_safety_error(span, did, violations)
             }
 
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index d5942e738fd..1d76ccdca31 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -13,7 +13,8 @@
 //! object if all of their methods meet certain criteria. In particular,
 //! they must:
 //!
-//!   - have a suitable receiver from which we can extract a vtable;
+//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
+//!     that doesn't contain the vtable;
 //!   - not reference the erased type `Self` except for in this receiver;
 //!   - not have generic type parameters
 
@@ -21,11 +22,12 @@ use super::elaborate_predicates;
 
 use hir::def_id::DefId;
 use lint;
-use traits;
-use ty::{self, Ty, TyCtxt, TypeFoldable};
-use ty::util::ExplicitSelf;
+use traits::{self, Obligation, ObligationCause};
+use ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate};
+use ty::subst::{Subst, Substs};
 use std::borrow::Cow;
-use syntax::ast;
+use std::iter::{self};
+use syntax::ast::{self, Name};
 use syntax_pos::Span;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -62,8 +64,8 @@ impl ObjectSafetyViolation {
                 format!("method `{}` references the `Self` type in where clauses", name).into(),
             ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
                 format!("method `{}` has generic type parameters", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::NonStandardSelfType) =>
-                format!("method `{}` has a non-standard `self` type", name).into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
+                format!("method `{}`'s receiver cannot be dispatched on", name).into(),
             ObjectSafetyViolation::AssociatedConst(name) =>
                 format!("the trait cannot contain associated consts like `{}`", name).into(),
         }
@@ -85,11 +87,11 @@ pub enum MethodViolationCode {
     /// e.g., `fn foo<A>()`
     Generic,
 
-    /// arbitrary `self` type, e.g. `self: Rc<Self>`
-    NonStandardSelfType,
+    /// the method's receiver (`self` argument) can't be dispatched on
+    UndispatchableReceiver,
 }
 
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 
     /// Returns the object safety violations that affect
     /// astconv - currently, Self in supertraits. This is needed
@@ -113,6 +115,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn object_safety_violations(self, trait_def_id: DefId)
                                     -> Vec<ObjectSafetyViolation>
     {
+        debug!("object_safety_violations: {:?}", trait_def_id);
+
         traits::supertrait_def_ids(self, trait_def_id)
             .flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
             .collect()
@@ -277,23 +281,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                          method: &ty::AssociatedItem)
                                          -> Option<MethodViolationCode>
     {
-        // The method's first parameter must be something that derefs (or
-        // autorefs) to `&self`. For now, we only accept `self`, `&self`
-        // and `Box<Self>`.
+        // The method's first parameter must be named `self`
         if !method.method_has_self_argument {
             return Some(MethodViolationCode::StaticMethod);
         }
 
         let sig = self.fn_sig(method.def_id);
 
-        let self_ty = self.mk_self_type();
-        let self_arg_ty = sig.skip_binder().inputs()[0];
-        if let ExplicitSelf::Other = ExplicitSelf::determine(self_arg_ty, |ty| ty == self_ty) {
-            return Some(MethodViolationCode::NonStandardSelfType);
-        }
-
-        // The `Self` type is erased, so it should not appear in list of
-        // arguments or return type apart from the receiver.
         for input_ty in &sig.skip_binder().inputs()[1..] {
             if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                 return Some(MethodViolationCode::ReferencesSelf);
@@ -320,9 +314,254 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
         }
 
+        let receiver_ty = self.liberate_late_bound_regions(
+            method.def_id,
+            &sig.map_bound(|sig| sig.inputs()[0]),
+        );
+
+        // 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_dispatchable(method, receiver_ty) {
+                return Some(MethodViolationCode::UndispatchableReceiver);
+            } else {
+                // sanity check to make sure the receiver actually has the layout of a pointer
+
+                use ty::layout::Abi;
+
+                let param_env = self.param_env(method.def_id);
+
+                let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
+                    match self.layout_of(param_env.and(ty)) {
+                        Ok(layout) => &layout.abi,
+                        Err(err) => bug!(
+                            "Error: {}\n while computing layout for type {:?}", err, ty
+                        )
+                    }
+                };
+
+                // e.g. Rc<()>
+                let unit_receiver_ty = self.receiver_for_self_ty(
+                    receiver_ty, self.mk_unit(), method.def_id
+                );
+
+                match abi_of_ty(unit_receiver_ty) {
+                    &Abi::Scalar(..) => (),
+                    abi => bug!("Receiver when Self = () should have a Scalar ABI, found {:?}", abi)
+                }
+
+                let trait_object_ty = self.object_ty_for_trait(
+                    trait_def_id, self.mk_region(ty::ReStatic)
+                );
+
+                // e.g. Rc<dyn Trait>
+                let trait_object_receiver = self.receiver_for_self_ty(
+                    receiver_ty, trait_object_ty, method.def_id
+                );
+
+                match abi_of_ty(trait_object_receiver) {
+                    &Abi::ScalarPair(..) => (),
+                    abi => bug!(
+                        "Receiver when Self = {} should have a ScalarPair ABI, found {:?}",
+                        trait_object_ty, abi
+                    )
+                }
+            }
+        }
+
         None
     }
 
+    /// performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
+    /// e.g. for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`
+    fn receiver_for_self_ty(
+        self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
+    ) -> Ty<'tcx> {
+        let substs = Substs::for_item(self, method_def_id, |param, _| {
+            if param.index == 0 {
+                self_ty.into()
+            } else {
+                self.mk_param_from_def(param)
+            }
+        });
+
+        receiver_ty.subst(self, substs)
+    }
+
+    /// creates the object type for the current trait. For example,
+    /// if the current trait is `Deref`, then this will be
+    /// `dyn Deref<Target=Self::Target> + 'static`
+    fn object_ty_for_trait(self, trait_def_id: DefId, lifetime: ty::Region<'tcx>) -> Ty<'tcx> {
+        debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
+
+        let trait_ref = ty::TraitRef::identity(self, trait_def_id);
+
+        let trait_predicate = ty::ExistentialPredicate::Trait(
+            ty::ExistentialTraitRef::erase_self_ty(self, trait_ref)
+        );
+
+        let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
+            .flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
+            .filter(|item| item.kind == ty::AssociatedKind::Type)
+            .collect::<Vec<_>>();
+
+        // existential predicates need to be in a specific order
+        associated_types.sort_by_key(|item| self.def_path_hash(item.def_id));
+
+        let projection_predicates = associated_types.into_iter().map(|item| {
+            ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
+                ty: self.mk_projection(item.def_id, trait_ref.substs),
+                item_def_id: item.def_id,
+                substs: trait_ref.substs,
+            })
+        });
+
+        let existential_predicates = self.mk_existential_predicates(
+            iter::once(trait_predicate).chain(projection_predicates)
+        );
+
+        let object_ty = self.mk_dynamic(
+            ty::Binder::dummy(existential_predicates),
+            lifetime,
+        );
+
+        debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
+
+        object_ty
+    }
+
+    /// 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:
+    ///
+    ///        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 Self: DispatchFromDyn<&'a mut dyn Trait>`
+    /// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`
+    /// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`
+    ///
+    /// 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 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, we cannot use `dyn Trait` explicitly in the obligation because it would result
+    /// in a new check that `Trait` is object safe, creating a cycle. So instead, we fudge a little
+    /// by introducing a new type parameter `U` such that `Self: Unsize<U>` and `U: Trait + ?Sized`,
+    /// and use `U` in place of `dyn Trait`. Written as a chalk-style query:
+    ///
+    ///     forall (U: Trait + ?Sized) {
+    ///         if (Self: Unsize<U>) {
+    ///             Receiver: DispatchFromDyn<Receiver[Self => U]>
+    ///         }
+    ///     }
+    ///
+    /// 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_dispatchable(
+        self,
+        method: &ty::AssociatedItem,
+        receiver_ty: Ty<'tcx>,
+    ) -> bool {
+        debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
+
+        let traits = (self.lang_items().unsize_trait(),
+                      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_dispatchable: Missing Unsize or DispatchFromDyn traits");
+            return false;
+        };
+
+        // the type `U` in the query
+        // 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 unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
+            ::std::u32::MAX,
+            Name::intern("RustaceansAreAwesome").as_interned_str(),
+        );
+
+        // `Receiver[Self => U]`
+        let unsized_receiver_ty = self.receiver_for_self_ty(
+            receiver_ty, unsized_self_ty, method.def_id
+        );
+
+        // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
+        // `U: ?Sized` is already implied here
+        let param_env = {
+            let mut param_env = self.param_env(method.def_id);
+
+            // Self: Unsize<U>
+            let unsize_predicate = ty::TraitRef {
+                def_id: unsize_did,
+                substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
+            }.to_predicate();
+
+            // U: Trait<Arg1, ..., ArgN>
+            let trait_predicate = {
+                let substs = Substs::for_item(self, method.container.assert_trait(), |param, _| {
+                    if param.index == 0 {
+                        unsized_self_ty.into()
+                    } else {
+                        self.mk_param_from_def(param)
+                    }
+                });
+
+                ty::TraitRef {
+                    def_id: unsize_did,
+                    substs,
+                }.to_predicate()
+            };
+
+            let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter().cloned()
+                .chain(iter::once(unsize_predicate))
+                .chain(iter::once(trait_predicate))
+                .collect();
+
+            param_env.caller_bounds = self.intern_predicates(&caller_bounds);
+
+            param_env
+        };
+
+        // Receiver: DispatchFromDyn<Receiver[Self => U]>
+        let obligation = {
+            let predicate = ty::TraitRef {
+                def_id: dispatch_from_dyn_did,
+                substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
+            }.to_predicate();
+
+            Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                predicate,
+            )
+        };
+
+        self.infer_ctxt().enter(|ref infcx| {
+            // the receiver is dispatchable iff the obligation holds
+            infcx.predicate_must_hold(&obligation)
+        })
+    }
+
     fn contains_illegal_self_type_reference(self,
                                             trait_def_id: DefId,
                                             ty: Ty<'tcx>)
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index e2a5fdd3622..ce515c45077 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2091,18 +2091,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             obligation.self_ty().skip_binder()
         );
 
-        // Object-safety candidates are only applicable to object-safe
-        // traits. Including this check is useful because it helps
-        // inference in cases of traits like `BorrowFrom`, which are
-        // not object-safe, and which rely on being able to infer the
-        // self-type from one of the other inputs. Without this check,
-        // these cases wind up being considered ambiguous due to a
-        // (spurious) ambiguity introduced here.
-        let predicate_trait_ref = obligation.predicate.to_poly_trait_ref();
-        if !self.tcx().is_object_safe(predicate_trait_ref.def_id()) {
-            return;
-        }
-
         self.probe(|this, _snapshot| {
             // the code below doesn't care about regions, and the
             // self-ty here doesn't escape this probe, so just erase
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 7c7662a88de..e50534a4e1d 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -19,7 +19,7 @@ use type_::Type;
 use type_of::{LayoutLlvmExt, PointerKind};
 use value::Value;
 
-use rustc_target::abi::{LayoutOf, Size, TyLayout};
+use rustc_target::abi::{LayoutOf, Size, TyLayout, Abi as LayoutAbi};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout;
 
@@ -302,21 +302,49 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
         FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
             let mut layout = cx.layout_of(ty);
             // Don't pass the vtable, it's not an argument of the virtual fn.
-            // Instead, pass just the (thin pointer) first field of `*dyn Trait`.
+            // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
+            // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
             if arg_idx == Some(0) {
-                // FIXME(eddyb) `layout.field(cx, 0)` is not enough because e.g.
-                // `Box<dyn Trait>` has a few newtype wrappers around the raw
-                // pointer, so we'd have to "dig down" to find `*dyn Trait`.
-                let pointee = if layout.is_unsized() {
-                    layout.ty
+                let fat_pointer_ty = if layout.is_unsized() {
+                    // unsized `self` is passed as a pointer to `self`
+                    // FIXME (mikeyhew) change this to use &own if it is ever added to the language
+                    cx.tcx.mk_mut_ptr(layout.ty)
                 } else {
-                    layout.ty.builtin_deref(true)
-                        .unwrap_or_else(|| {
-                            bug!("FnType::new_vtable: non-pointer self {:?}", layout)
-                        }).ty
+                    match layout.abi {
+                        LayoutAbi::ScalarPair(..) => (),
+                        _ => bug!("receiver type has unsupported layout: {:?}", layout)
+                    }
+
+                    // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
+                    // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
+                    // elsewhere in the compiler as a method on a `dyn Trait`.
+                    // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
+                    // get a built-in pointer type
+                    let mut fat_pointer_layout = layout;
+                    'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
+                        && !fat_pointer_layout.ty.is_region_ptr()
+                    {
+                        'iter_fields: for i in 0..fat_pointer_layout.fields.count() {
+                            let field_layout = fat_pointer_layout.field(cx, i);
+
+                            if !field_layout.is_zst() {
+                                fat_pointer_layout = field_layout;
+                                continue 'descend_newtypes
+                            }
+                        }
+
+                        bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
+                    }
+
+                    fat_pointer_layout.ty
                 };
-                let fat_ptr_ty = cx.tcx.mk_mut_ptr(pointee);
-                layout = cx.layout_of(fat_ptr_ty).field(cx, 0);
+
+                // we now have a type like `*mut RcBox<dyn Trait>`
+                // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
+                // this is understood as a special case elsewhere in the compiler
+                let unit_pointer_ty = cx.tcx.mk_mut_ptr(cx.tcx.mk_unit());
+                layout = cx.layout_of(unit_pointer_ty);
+                layout.ty = fat_pointer_ty;
             }
             ArgType::new(layout)
         })
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs
index d98b7869ae9..a7f4c48c89b 100644
--- a/src/librustc_codegen_llvm/mir/block.rs
+++ b/src/librustc_codegen_llvm/mir/block.rs
@@ -642,14 +642,46 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     (&args[..], None)
                 };
 
-                for (i, arg) in first_args.iter().enumerate() {
+                'make_args: for (i, arg) in first_args.iter().enumerate() {
                     let mut op = self.codegen_operand(&bx, arg);
+
                     if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
-                        if let Pair(data_ptr, meta) = op.val {
-                            llfn = Some(meth::VirtualIndex::from_index(idx)
-                                .get_fn(&bx, meta, &fn_ty));
-                            llargs.push(data_ptr);
-                            continue;
+                        if let Pair(..) = op.val {
+                            // In the case of Rc<Self>, we need to explicitly pass a
+                            // *mut RcBox<Self> with a Scalar (not ScalarPair) ABI. This is a hack
+                            // that is understood elsewhere in the compiler as a method on
+                            // `dyn Trait`.
+                            // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
+                            // we get a value of a built-in pointer type
+                            'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
+                                            && !op.layout.ty.is_region_ptr()
+                            {
+                                'iter_fields: for i in 0..op.layout.fields.count() {
+                                    let field = op.extract_field(&bx, i);
+                                    if !field.layout.is_zst() {
+                                        // we found the one non-zero-sized field that is allowed
+                                        // now find *its* non-zero-sized field, or stop if it's a
+                                        // pointer
+                                        op = field;
+                                        continue 'descend_newtypes
+                                    }
+                                }
+
+                                span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
+                            }
+
+                            // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
+                            // data pointer and vtable. Look up the method in the vtable, and pass
+                            // the data pointer as the first argument
+                            match op.val {
+                                Pair(data_ptr, meta) => {
+                                    llfn = Some(meth::VirtualIndex::from_index(idx)
+                                        .get_fn(&bx, meta, &fn_ty));
+                                    llargs.push(data_ptr);
+                                    continue 'make_args
+                                }
+                                other => bug!("expected a Pair, got {:?}", other)
+                            }
                         } else if let Ref(data_ptr, Some(meta), _) = op.val {
                             // by-value dynamic dispatch
                             llfn = Some(meth::VirtualIndex::from_index(idx)
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 7ddc56974d8..afd8c251b76 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1013,7 +1013,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         // most importantly, that the supertraits don't contain Self,
         // to avoid ICE-s.
         let object_safety_violations =
-            tcx.astconv_object_safety_violations(principal.def_id());
+            tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
         if !object_safety_violations.is_empty() {
             tcx.report_object_safety_error(
                 span, principal.def_id(), object_safety_violations)
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 05a83dd307c..99c6ba457fa 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -31,8 +31,9 @@ pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
         .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_unsized_trait(), visit_implementation_of_coerce_unsized)
+        .check(tcx.lang_items().dispatch_from_dyn_trait(),
+            visit_implementation_of_dispatch_from_dyn);
 }
 
 struct Checker<'a, 'tcx: 'a> {
@@ -162,6 +163,174 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+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 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);
+
+        let source = tcx.type_of(impl_did);
+        assert!(!source.has_escaping_regions());
+        let target = {
+            let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+            assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
+
+            trait_ref.substs.type_at(1)
+        };
+
+        debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}",
+            source,
+            target);
+
+        let param_env = tcx.param_env(impl_did);
+
+        let create_err = |msg: &str| {
+            struct_span_err!(tcx.sess, span, E0378, "{}", msg)
+        };
+
+        tcx.infer_ctxt().enter(|infcx| {
+            let cause = ObligationCause::misc(span, impl_node_id);
+
+            use ty::TyKind::*;
+            match (&source.sty, &target.sty) {
+                (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
+                    if infcx.at(&cause, param_env).eq(r_a, r_b).is_ok()
+                    && mutbl_a == *mutbl_b => (),
+                (&RawPtr(tm_a), &RawPtr(tm_b))
+                    if tm_a.mutbl == tm_b.mutbl => (),
+                (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
+                    if def_a.is_struct() && def_b.is_struct() =>
+                {
+                    if def_a != def_b {
+                        let source_path = tcx.item_path_str(def_a.did);
+                        let target_path = tcx.item_path_str(def_b.did);
+
+                        create_err(
+                            &format!(
+                                "the trait `DispatchFromDyn` may only be implemented \
+                                for a coercion between structures with the same \
+                                definition; expected `{}`, found `{}`",
+                                source_path, target_path,
+                            )
+                        ).emit();
+
+                        return
+                    }
+
+                    if def_a.repr.c() || def_a.repr.packed() {
+                        create_err(
+                            "structs implementing `DispatchFromDyn` may not have \
+                             `#[repr(packed)]` or `#[repr(C)]`"
+                        ).emit();
+                    }
+
+                    let fields = &def_a.non_enum_variant().fields;
+
+                    let coerced_fields = fields.iter().filter_map(|field| {
+                        if tcx.type_of(field.did).is_phantom_data() {
+                            // ignore PhantomData fields
+                            return None
+                        }
+
+                        let ty_a = field.ty(tcx, substs_a);
+                        let ty_b = field.ty(tcx, substs_b);
+                        if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
+                            if ok.obligations.is_empty() {
+                                create_err(
+                                    "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",
+                                        field.ident, ty_a,
+                                    )
+                                ).emit();
+
+                                return None;
+                            }
+                        }
+
+                        Some(field)
+                    }).collect::<Vec<_>>();
+
+                    if coerced_fields.is_empty() {
+                        create_err(
+                            "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 `DispatchFromDyn` trait requires multiple coercions",
+                        ).note(
+                            "the trait `DispatchFromDyn` may only be implemented \
+                                for a coercion between structures with a single field \
+                                being coerced"
+                        ).note(
+                            &format!(
+                                "currently, {} fields need coercions: {}",
+                                coerced_fields.len(),
+                                coerced_fields.iter().map(|field| {
+                                    format!("`{}` (`{}` to `{}`)",
+                                        field.ident,
+                                        field.ty(tcx, substs_a),
+                                        field.ty(tcx, substs_b),
+                                    )
+                                }).collect::<Vec<_>>()
+                                .join(", ")
+                            )
+                        ).emit();
+                    } else {
+                        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+
+                        for field in coerced_fields {
+
+                            let predicate = tcx.predicate_for_trait_def(
+                                param_env,
+                                cause.clone(),
+                                dispatch_from_dyn_trait,
+                                0,
+                                field.ty(tcx, substs_a),
+                                &[field.ty(tcx, substs_b).into()]
+                            );
+
+                            fulfill_cx.register_predicate_obligation(&infcx, predicate);
+                        }
+
+                        // Check that all transitive obligations are satisfied.
+                        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+                            infcx.report_fulfillment_errors(&errors, None, false);
+                        }
+
+                        // Finally, resolve all regions.
+                        let region_scope_tree = region::ScopeTree::default();
+                        let outlives_env = OutlivesEnvironment::new(param_env);
+                        infcx.resolve_regions_and_report_errors(
+                            impl_did,
+                            &region_scope_tree,
+                            &outlives_env,
+                            SuppressRegionErrors::default(),
+                        );
+                    }
+                }
+                _ => {
+                    create_err(
+                        "the trait `DispatchFromDyn` may only be implemented \
+                        for a coercion between structures"
+                    ).emit();
+                }
+            }
+        })
+    }
+}
+
 pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                                      impl_did: DefId)
                                      -> CoerceUnsizedInfo {
@@ -236,7 +405,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                               E0377,
                               "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures with the same \
-                               definition; expected {}, found {}",
+                               definition; expected `{}`, found `{}`",
                               source_path,
                               target_path);
                     return err_info;
@@ -341,7 +510,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                                       diff_fields.len(),
                                       diff_fields.iter()
                                           .map(|&(i, a, b)| {
-                                              format!("{} ({} to {})", fields[i].ident, a, b)
+                                              format!("`{}` (`{}` to `{}`)", fields[i].ident, a, b)
                                           })
                                           .collect::<Vec<_>>()
                                           .join(", ")));
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index f57d050fa2d..c81aea2465b 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -3084,6 +3084,66 @@ containing the unsized type is the last and only unsized type field in the
 struct.
 "##,
 
+E0378: r##"
+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(dispatch_from_dyn, unsize)]
+use std::{
+    marker::Unsize,
+    ops::DispatchFromDyn,
+};
+
+struct Ptr<T: ?Sized>(*const T);
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T>
+where
+    T: Unsize<U>,
+{}
+```
+
+```
+#![feature(dispatch_from_dyn)]
+use std::{
+    ops::DispatchFromDyn,
+    marker::PhantomData,
+};
+
+struct Wrapper<T> {
+    ptr: T,
+    _phantom: PhantomData<()>,
+}
+
+impl<T, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T>
+where
+    T: DispatchFromDyn<U>,
+{}
+```
+
+Example of illegal `DispatchFromDyn` implementation
+(illegal because of extra field)
+
+```compile-fail,E0378
+#![feature(dispatch_from_dyn)]
+use std::ops::DispatchFromDyn;
+
+struct WrapperExtraField<T> {
+    ptr: T,
+    extra_stuff: i32,
+}
+
+impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T>
+where
+    T: DispatchFromDyn<U>,
+{}
+```
+"##,
+
 E0390: r##"
 You tried to implement methods for a primitive type. Erroneous code example:
 
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
new file mode 100644
index 00000000000..e1663563cec
--- /dev/null
+++ b/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs
@@ -0,0 +1,76 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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, dispatch_from_dyn)]
+#![feature(rustc_attrs)]
+
+use std::{
+    ops::{Deref, CoerceUnsized, DispatchFromDyn},
+    marker::Unsize,
+};
+
+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> {}
+impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
+
+struct Wrapper<T: ?Sized>(T);
+
+impl<T: ?Sized> Deref for Wrapper<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
+
+
+trait Trait {
+    // 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;
+    fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
+}
+
+impl Trait for i32 {
+    fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
+        **self
+    }
+    fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 {
+        **self
+    }
+    fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
+        ***self
+    }
+}
+
+fn main() {
+    let pw = Ptr(Box::new(Wrapper(5))) as Ptr<Wrapper<dyn Trait>>;
+    assert_eq!(pw.ptr_wrapper(), 5);
+
+    let wp = Wrapper(Ptr(Box::new(6))) as Wrapper<Ptr<dyn Trait>>;
+    assert_eq!(wp.wrapper_ptr(), 6);
+
+    let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
+    assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
+}
diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
new file mode 100644
index 00000000000..80a7ce96911
--- /dev/null
+++ b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
@@ -0,0 +1,56 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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)]
+#![feature(pin)]
+#![feature(rustc_attrs)]
+
+use std::{
+    rc::Rc,
+    sync::Arc,
+    pin::Pin,
+};
+
+trait Trait {
+    fn by_rc(self: Rc<Self>) -> i64;
+    fn by_arc(self: Arc<Self>) -> i64;
+    fn by_pin_mut(self: Pin<&mut Self>) -> i64;
+    fn by_pin_box(self: Pin<Box<Self>>) -> i64;
+}
+
+impl Trait for i64 {
+    fn by_rc(self: Rc<Self>) -> i64 {
+        *self
+    }
+    fn by_arc(self: Arc<Self>) -> i64 {
+        *self
+    }
+    fn by_pin_mut(self: Pin<&mut Self>) -> i64 {
+        *self
+    }
+    fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
+        *self
+    }
+}
+
+fn main() {
+    let rc = Rc::new(1i64) as Rc<dyn Trait>;
+    assert_eq!(1, rc.by_rc());
+
+    let arc = Arc::new(2i64) as Arc<dyn Trait>;
+    assert_eq!(2, arc.by_arc());
+
+    let mut value = 3i64;
+    let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>;
+    assert_eq!(3, pin_mut.by_pin_mut());
+
+    let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
+    assert_eq!(4, pin_box.by_pin_box());
+}
diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.rs b/src/test/ui/arbitrary-self-types-not-object-safe.rs
index 48918b996ef..4dc481174a4 100644
--- a/src/test/ui/arbitrary-self-types-not-object-safe.rs
+++ b/src/test/ui/arbitrary-self-types-not-object-safe.rs
@@ -12,38 +12,38 @@
 use std::rc::Rc;
 
 trait Foo {
-    fn foo(self: Rc<Self>) -> usize;
+    fn foo(self: &Rc<Self>) -> usize;
 }
 
 trait Bar {
-    fn foo(self: Rc<Self>) -> usize where Self: Sized;
-    fn bar(self: Box<Self>) -> usize;
+    fn foo(self: &Rc<Self>) -> usize where Self: Sized;
+    fn bar(self: Rc<Self>) -> usize;
 }
 
 impl Foo for usize {
-    fn foo(self: Rc<Self>) -> usize {
-        *self
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
     }
 }
 
 impl Bar for usize {
-    fn foo(self: Rc<Self>) -> usize {
-        *self
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
     }
 
-    fn bar(self: Box<Self>) -> usize {
+    fn bar(self: Rc<Self>) -> usize {
         *self
     }
 }
 
 fn make_foo() {
-    let x = Box::new(5usize) as Box<Foo>;
+    let x = Rc::new(5usize) as Rc<Foo>;
     //~^ ERROR E0038
     //~| ERROR E0038
 }
 
 fn make_bar() {
-    let x = Box::new(5usize) as Box<Bar>;
+    let x = Rc::new(5usize) as Rc<Bar>;
     x.bar();
 }
 
diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/arbitrary-self-types-not-object-safe.stderr
index ec9e65fc4c6..77ca118471d 100644
--- a/src/test/ui/arbitrary-self-types-not-object-safe.stderr
+++ b/src/test/ui/arbitrary-self-types-not-object-safe.stderr
@@ -1,19 +1,19 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/arbitrary-self-types-not-object-safe.rs:40:33
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:40:32
    |
-LL |     let x = Box::new(5usize) as Box<Foo>;
-   |                                 ^^^^^^^^ the trait `Foo` cannot be made into an object
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |                                ^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo` has a non-standard `self` type
+   = note: method `foo`'s receiver cannot be dispatched on
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:40:13
    |
-LL |     let x = Box::new(5usize) as Box<Foo>;
-   |             ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo` has a non-standard `self` type
-   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
+   = note: method `foo`'s receiver cannot be dispatched on
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0375.stderr b/src/test/ui/error-codes/E0375.stderr
index 3ffd25084b8..f3db697790c 100644
--- a/src/test/ui/error-codes/E0375.stderr
+++ b/src/test/ui/error-codes/E0375.stderr
@@ -5,7 +5,7 @@ LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
    |
    = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
-   = note: currently, 2 fields need coercions: b (T to U), c (U to T)
+   = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
new file mode 100644
index 00000000000..1cf5c73ab13
--- /dev/null
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
@@ -0,0 +1,52 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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(unsize, dispatch_from_dyn)]
+
+use std::{
+    ops::DispatchFromDyn,
+    marker::{Unsize, PhantomData},
+};
+
+struct WrapperWithExtraField<T>(T, i32);
+
+impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+where
+    T: DispatchFromDyn<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct MultiplePointers<T: ?Sized>{
+    ptr1: *const T,
+    ptr2: *const T,
+}
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
+where
+    T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct NothingToCoerce<T: ?Sized> {
+    data: PhantomData<T>,
+}
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
+//~^ ERROR [E0378]
+
+#[repr(C)]
+struct HasReprC<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
+where
+    T: Unsize<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..82186b67d97
--- /dev/null
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
@@ -0,0 +1,41 @@
+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[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:47:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
+LL | | where
+LL | |     T: Unsize<U>,
+LL | | {} //~^^^ ERROR [E0378]
+   | |__^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0378`.
diff --git a/src/test/ui/issues/issue-26905.stderr b/src/test/ui/issues/issue-26905.stderr
index f18b58a8330..7feabef5660 100644
--- a/src/test/ui/issues/issue-26905.stderr
+++ b/src/test/ui/issues/issue-26905.stderr
@@ -5,7 +5,7 @@ LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{
    |                                        ^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
    |
    = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
-   = note: currently, 2 fields need coercions: _ptr (*const T to *const U), _boo (NotPhantomData<T> to NotPhantomData<U>)
+   = note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData<T>` to `NotPhantomData<U>`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs
index f8e4f0d596e..1db5ec09737 100644
--- a/src/test/ui/traits/trait-item-privacy.rs
+++ b/src/test/ui/traits/trait-item-privacy.rs
@@ -110,9 +110,7 @@ fn check_assoc_const() {
     // A, B, C are resolved as inherent items, their traits don't need to be in scope
     C::A; //~ ERROR associated constant `A` is private
           //~^ ERROR the trait `assoc_const::C` cannot be made into an object
-          //~| ERROR the trait bound `dyn assoc_const::C: assoc_const::A` is not satisfied
     C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
-          //~^ ERROR the trait bound `dyn assoc_const::C: assoc_const::B` is not satisfied
     C::C; // OK
 }
 
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
index fc14ae91d7b..4ede83d5d73 100644
--- a/src/test/ui/traits/trait-item-privacy.stderr
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -100,30 +100,6 @@ error[E0624]: associated constant `A` is private
 LL |     C::A; //~ ERROR associated constant `A` is private
    |     ^^^^
 
-error[E0277]: the trait bound `dyn assoc_const::C: assoc_const::A` is not satisfied
-  --> $DIR/trait-item-privacy.rs:111:5
-   |
-LL |     C::A; //~ ERROR associated constant `A` is private
-   |     ^^^^ the trait `assoc_const::A` is not implemented for `dyn assoc_const::C`
-   |
-note: required by `assoc_const::A::A`
-  --> $DIR/trait-item-privacy.rs:35:9
-   |
-LL |         const A: u8 = 0;
-   |         ^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `dyn assoc_const::C: assoc_const::B` is not satisfied
-  --> $DIR/trait-item-privacy.rs:114:5
-   |
-LL |     C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
-   |     ^^^^ the trait `assoc_const::B` is not implemented for `dyn assoc_const::C`
-   |
-note: required by `assoc_const::B::B`
-  --> $DIR/trait-item-privacy.rs:39:9
-   |
-LL |         const B: u8 = 0;
-   |         ^^^^^^^^^^^^^^^^
-
 error[E0038]: the trait `assoc_const::C` cannot be made into an object
   --> $DIR/trait-item-privacy.rs:111:5
    |
@@ -135,36 +111,36 @@ LL |     C::A; //~ ERROR associated constant `A` is private
    = note: the trait cannot contain associated consts like `A`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/trait-item-privacy.rs:127:12
+  --> $DIR/trait-item-privacy.rs:125:12
    |
 LL |     let _: S::A; //~ ERROR ambiguous associated type
    |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/trait-item-privacy.rs:128:12
+  --> $DIR/trait-item-privacy.rs:126:12
    |
 LL |     let _: S::B; //~ ERROR ambiguous associated type
    |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::B`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/trait-item-privacy.rs:129:12
+  --> $DIR/trait-item-privacy.rs:127:12
    |
 LL |     let _: S::C; //~ ERROR ambiguous associated type
    |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
 
 error: associated type `A` is private
-  --> $DIR/trait-item-privacy.rs:131:12
+  --> $DIR/trait-item-privacy.rs:129:12
    |
 LL |     let _: T::A; //~ ERROR associated type `A` is private
    |            ^^^^
 
 error: associated type `A` is private
-  --> $DIR/trait-item-privacy.rs:140:9
+  --> $DIR/trait-item-privacy.rs:138:9
    |
 LL |         A = u8, //~ ERROR associated type `A` is private
    |         ^^^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 15 previous errors
 
-Some errors occurred: E0038, E0223, E0277, E0599, E0624.
+Some errors occurred: E0038, E0223, E0599, E0624.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-test-2.rs b/src/test/ui/traits/trait-test-2.rs
index dac76fb57fd..01d7e89847a 100644
--- a/src/test/ui/traits/trait-test-2.rs
+++ b/src/test/ui/traits/trait-test-2.rs
@@ -20,5 +20,4 @@ fn main() {
     (box 10 as Box<bar>).dup();
     //~^ ERROR E0038
     //~| ERROR E0038
-    //~| ERROR E0277
 }
diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr
index 1e1fcbe340e..db0cd38cb6a 100644
--- a/src/test/ui/traits/trait-test-2.stderr
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -10,12 +10,6 @@ error[E0107]: wrong number of type arguments: expected 1, found 2
 LL |     10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
    |                    ^^^ unexpected type argument
 
-error[E0277]: the trait bound `dyn bar: bar` is not satisfied
-  --> $DIR/trait-test-2.rs:20:26
-   |
-LL |     (box 10 as Box<bar>).dup();
-   |                          ^^^ the trait `bar` is not implemented for `dyn bar`
-
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/trait-test-2.rs:20:16
    |
@@ -35,7 +29,7 @@ LL |     (box 10 as Box<bar>).dup();
    = note: method `blah` has generic type parameters
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0038, E0107, E0277.
+Some errors occurred: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.