about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2015-05-12 14:41:08 +1200
committerNick Cameron <ncameron@mozilla.com>2015-05-13 14:35:53 +1200
commit5d4cce6cec7c0975263bbe6f4260167a772bfc89 (patch)
tree1dba65dbc1d9332fe808af52bc82951b3f453c8b
parentdb1b14a194cbdbba813aeb4773ee7fa203a40fb1 (diff)
downloadrust-5d4cce6cec7c0975263bbe6f4260167a772bfc89.tar.gz
rust-5d4cce6cec7c0975263bbe6f4260167a772bfc89.zip
Rebasing
-rw-r--r--src/liballoc/rc.rs4
-rw-r--r--src/libcore/cell.rs1
-rw-r--r--src/libcore/ops.rs9
-rw-r--r--src/libcoretest/cell.rs23
-rw-r--r--src/librustc/diagnostics.rs2
-rw-r--r--src/librustc/middle/traits/select.rs7
-rw-r--r--src/librustc/middle/traits/util.rs2
-rw-r--r--src/librustc/middle/ty.rs2
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs8
-rw-r--r--src/librustc_trans/trans/expr.rs4
-rw-r--r--src/librustc_typeck/check/cast.rs55
-rw-r--r--src/librustc_typeck/check/coercion.rs10
-rw-r--r--src/librustc_typeck/check/regionck.rs1
-rw-r--r--src/librustc_typeck/coherence/mod.rs41
-rw-r--r--src/librustc_typeck/coherence/orphan.rs2
-rw-r--r--src/librustc_typeck/diagnostics.rs6
-rw-r--r--src/libstd/sync/mutex.rs23
-rw-r--r--src/libstd/sync/rwlock.rs23
-rw-r--r--src/test/compile-fail/fat-ptr-cast.rs4
19 files changed, 118 insertions, 109 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 837cf590024..15d6e6fa960 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -460,7 +460,6 @@ impl<T: ?Sized> Deref for Rc<T> {
 }
 
 #[cfg(stage0)] // SNAP c64d671
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Rc<T> {
     /// Drops the `Rc<T>`.
@@ -512,7 +511,6 @@ impl<T> Drop for Rc<T> {
 }
 
 #[cfg(not(stage0))] // SNAP c64d671
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for Rc<T> {
     /// Drops the `Rc<T>`.
@@ -933,7 +931,6 @@ impl<T: ?Sized> Weak<T> {
 }
 
 #[cfg(stage0)] // SNAP c64d671
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
@@ -979,7 +976,6 @@ impl<T> Drop for Weak<T> {
 }
 
 #[cfg(not(stage0))] // SNAP c64d671
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index bf5fdb973eb..45a80122104 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -707,5 +707,4 @@ impl<T: ?Sized> UnsafeCell<T> {
         #![allow(trivial_casts)]
         &self.value as *const T as *mut T
     }
-
 }
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 1a2473fda41..9396adc0fe5 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -1220,24 +1220,33 @@ pub trait CoerceUnsized<T> {
     // Empty.
 }
 
+// &mut T -> &mut U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
+// &mut T -> &U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
+// &mut T -> *mut U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
+// &mut T -> *const U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
 
+// &T -> &U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+// &T -> *const U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
 
+// *mut T -> *mut U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
+// *mut T -> *const U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
 
+// *const T -> *const U
 #[cfg(not(stage0))] // SNAP c64d671
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs
index 0bd0b66318f..f02312b8641 100644
--- a/src/libcoretest/cell.rs
+++ b/src/libcoretest/cell.rs
@@ -172,14 +172,15 @@ fn unsafe_cell_unsized() {
     assert_eq!(unsafe { &mut *cell.get() }, comp);
 }
 
-#[test]
-fn refcell_unsized() {
-    let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
-    {
-        let b = &mut *cell.borrow_mut();
-        b[0] = 4;
-        b[2] = 5;
-    }
-    let comp: &mut [i32] = &mut [4, 2, 5];
-    assert_eq!(&*cell.borrow(), comp);
-}
+// FIXME(#25351) needs deeply nested coercions of DST structs.
+// #[test]
+// fn refcell_unsized() {
+//     let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
+//     {
+//         let b = &mut *cell.borrow_mut();
+//         b[0] = 4;
+//         b[2] = 5;
+//     }
+//     let comp: &mut [i32] = &mut [4, 2, 5];
+//     assert_eq!(&*cell.borrow(), comp);
+// }
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index c8788f76081..bb50d5110cb 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -808,8 +808,6 @@ register_diagnostics! {
     E0019,
     E0022,
     E0038,
-    E0079, // enum variant: expected signed integer constant
-    E0080, // enum variant: constant evaluation error
     E0109,
     E0110,
     E0134,
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 2541bba5d9a..a4ed73d7358 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1369,7 +1369,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn assemble_candidates_for_unsizing(&mut self,
                                         obligation: &TraitObligation<'tcx>,
                                         candidates: &mut SelectionCandidateSet<'tcx>) {
-        // TODO is it Ok to skip the binder here?
+        // It is ok to skip past the higher-ranked binders here because the `match`
+        // below does not consider regions at all.
         let source = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
 
@@ -1494,7 +1495,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 &ClosureCandidate(..) |
                 &FnPointerCandidate(..) |
                 &BuiltinObjectCandidate(..) |
-                &&BuiltinUnsizeCandidate(..) |
+                &BuiltinUnsizeCandidate(..) |
                 &DefaultImplObjectCandidate(..) |
                 &BuiltinCandidate(..) => {
                     // We have a where-clause so don't go around looking
@@ -2498,7 +2499,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::lookup_field_type_unsubstituted(tcx, def_id, f.id)
                 }).collect::<Vec<_>>();
 
-                // The last field of the structure has to exist and be a
+                // FIXME(#25351) The last field of the structure has to exist and be a
                 // type parameter (for now, to avoid tracking edge cases).
                 let i = if let Some(&ty::ty_param(p)) = fields.last().map(|ty| &ty.sty) {
                     assert!(p.space == TypeSpace);
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index ea4bc029ed6..f30f8560b9f 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -377,7 +377,7 @@ pub fn predicate_for_trait_def<'tcx>(
     let trait_ref = ty::TraitRef {
         def_id: trait_def_id,
         substs: tcx.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
-    });
+    };
     predicate_for_trait_ref(cause, trait_ref, recursion_depth)
 }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 5a84edd3cdf..9054cd65473 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4420,7 +4420,7 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
 pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_uniq(ty) => ty,
-        ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
+        ty_rptr(_, mt) | ty_ptr(mt) => mt.ty,
         _ => ty
     }
 }
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index bd04bd7a754..ab86cd7cdde 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -1058,6 +1058,7 @@ impl MetadataCreationResult {
     }
 }
 
+#[derive(Debug)]
 enum MemberOffset {
     FixedMemberOffset { bytes: usize },
     // For ComputedMemberOffset, the offset is read from the llvm type definition.
@@ -1066,6 +1067,7 @@ enum MemberOffset {
 
 // Description of a type member, which can either be a regular field (as in
 // structs or tuples) or an enum variant.
+#[derive(Debug)]
 struct MemberDescription {
     name: String,
     llvm_type: Type,
@@ -1163,13 +1165,13 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                      span: Span)
                                      -> RecursiveTypeDescription<'tcx> {
     let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
-    let struct_llvm_type = type_of::type_of(cx, struct_type);
+    let struct_llvm_type = type_of::in_memory_type_of(cx, struct_type);
 
     let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
 
     let struct_metadata_stub = create_struct_stub(cx,
                                                   struct_llvm_type,
-                                                  &struct_name[..],
+                                                  &struct_name,
                                                   unique_type_id,
                                                   containing_scope);
 
@@ -1299,7 +1301,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                         set_members_of_composite_type(cx,
                                                       variant_type_metadata,
                                                       variant_llvm_type,
-                                                      &member_descriptions[..]);
+                                                      &member_descriptions);
                         MemberDescription {
                             name: "".to_string(),
                             llvm_type: variant_llvm_type,
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 4018df0da47..270aacfe143 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -487,11 +487,11 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let trait_substs = Substs::erased(VecPerParamSpace::new(vec![target.ty],
                                                                     vec![source.ty],
                                                                     Vec::new()));
-            let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
+            let trait_ref = ty::Binder(ty::TraitRef {
                 def_id: langcall(bcx, Some(span), "coercion",
                                  CoerceUnsizedTraitLangItem),
                 substs: bcx.tcx().mk_substs(trait_substs)
-            }));
+            });
 
             let kind = match fulfill_obligation(bcx.ccx(), span, trait_ref) {
                 traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index bfd159720c2..bc6159c0cff 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -60,28 +60,29 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
     let e = &cast.expr;
     let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
     let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
+    let tcx = fcx.tcx();
 
     // Check for trivial casts.
     if !ty::type_has_ty_infer(t_1) {
         if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
             if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
-                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
-                                        e.id,
-                                        span,
-                                        format!("trivial numeric cast: `{}` as `{}`. Cast can be \
-                                                 replaced by coercion, this might require type \
-                                                 ascription or a temporary variable",
-                                                fcx.infcx().ty_to_string(t_e),
-                                                fcx.infcx().ty_to_string(t_1)));
+                tcx.sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
+                                  e.id,
+                                  span,
+                                  format!("trivial numeric cast: `{}` as `{}`. Cast can be \
+                                           replaced by coercion, this might require type \
+                                           ascription or a temporary variable",
+                                          fcx.infcx().ty_to_string(t_e),
+                                          fcx.infcx().ty_to_string(t_1)));
             } else {
-                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
-                                        e.id,
-                                        span,
-                                        format!("trivial cast: `{}` as `{}`. Cast can be \
-                                                 replaced by coercion, this might require type \
-                                                 ascription or a temporary variable",
-                                                fcx.infcx().ty_to_string(t_e),
-                                                fcx.infcx().ty_to_string(t_1)));
+                tcx.sess.add_lint(lint::builtin::TRIVIAL_CASTS,
+                                  e.id,
+                                  span,
+                                  format!("trivial cast: `{}` as `{}`. Cast can be \
+                                           replaced by coercion, this might require type \
+                                           ascription or a temporary variable",
+                                          fcx.infcx().ty_to_string(t_e),
+                                          fcx.infcx().ty_to_string(t_1)));
             }
             return;
         }
@@ -91,14 +92,14 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
     let t_e_is_scalar = ty::type_is_scalar(t_e);
     let t_e_is_integral = ty::type_is_integral(t_e);
     let t_e_is_float = ty::type_is_floating_point(t_e);
-    let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
+    let t_e_is_c_enum = ty::type_is_c_like_enum(tcx, t_e);
 
     let t_1_is_scalar = ty::type_is_scalar(t_1);
     let t_1_is_integral = ty::type_is_integral(t_1);
     let t_1_is_char = ty::type_is_char(t_1);
     let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
     let t_1_is_float = ty::type_is_floating_point(t_1);
-    let t_1_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_1);
+    let t_1_is_c_enum = ty::type_is_c_like_enum(tcx, t_1);
     let t1_is_fat_ptr = fcx.type_is_fat_ptr(t_1, span);
 
     // casts to scalars other than `char` and `bare fn` are trivial
@@ -114,7 +115,7 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
             }, t_e, None);
         }
     } else if t_1.sty == ty::ty_bool {
-        span_err!(fcx.tcx().sess, span, E0054,
+        span_err!(tcx.sess, span, E0054,
                   "cannot cast as `bool`, compare with zero instead");
     } else if t_e_is_float && (t_1_is_scalar || t_1_is_c_enum) &&
         !(t_1_is_integral || t_1_is_float) {
@@ -174,12 +175,16 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
     } else if t1_is_fat_ptr {
         // FIXME This should be allowed where the lefthandside is also a fat
         // pointer and is the same kind of fat pointer, i.e., array to array,
-        // trait object to trait object.
-        fcx.type_error_message(span, |actual| {
-            format!("cast to fat pointer: `{}` as `{}`",
-                    actual,
-                    fcx.infcx().ty_to_string(t_1))
-        }, t_e, None);
+        // trait object to trait object. That is a bit looser than the current
+        // rquirement that they are pointers to the same type.
+        if !(fcx.type_is_fat_ptr(t_e, span) &&
+             ty::deref(t_1, true).unwrap().ty == ty::deref(t_e, true).unwrap().ty) {
+            fcx.type_error_message(span, |actual| {
+                format!("cast to fat pointer: `{}` as `{}`",
+                        actual,
+                        fcx.infcx().ty_to_string(t_1))
+            }, t_e, None);
+        }
     } else if !(t_e_is_scalar && t_1_is_trivial) {
         fcx.type_error_message(span, |actual| {
             format!("non-scalar cast: `{}` as `{}`",
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index d33553f3859..dd63a512ae3 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -285,14 +285,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Create an obligation for `Source: CoerceUnsized<Target>`.
         let cause = ObligationCause::misc(self.origin.span(), self.fcx.body_id);
-        queue.push_back(predicate_for_trait_def(self.tcx(), cause, coerce_unsized_did,
-                                                0, source, vec![target]));
+        queue.push_back(predicate_for_trait_def(self.tcx(),
+                                                cause,
+                                                coerce_unsized_did,
+                                                0,
+                                                source,
+                                                vec![target]));
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
         // inference might unify those two inner type variables later.
         let traits = [coerce_unsized_did, unsize_did];
         while let Some(obligation) = queue.pop_front() {
+            debug!("coerce_unsized resolve step: {}", obligation.repr(self.tcx()));
             let trait_ref =  match obligation.predicate {
                 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
                     tr.clone()
@@ -305,6 +310,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             match selcx.select(&obligation.with(trait_ref)) {
                 // Uncertain or unimplemented.
                 Ok(None) | Err(traits::Unimplemented) => {
+                    debug!("coerce_unsized: early return - can't prove obligation");
                     return Err(ty::terr_mismatch);
                 }
 
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 337088c313d..090d111b62b 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -85,6 +85,7 @@
 use astconv::AstConv;
 use check::dropck;
 use check::FnCtxt;
+use middle::free_region::FreeRegionMap;
 use middle::implicator;
 use middle::mem_categorization as mc;
 use middle::region::CodeExtent;
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index c6e0bb676f7..58ad8ce8628 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -29,6 +29,7 @@ use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int};
 use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
 use middle::ty::ty_projection;
 use middle::ty;
+use middle::free_region::FreeRegionMap;
 use CrateCtxt;
 use middle::infer::{self, InferCtxt, new_infer_ctxt};
 use std::cell::RefCell;
@@ -439,32 +440,19 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
         };
 
-        let trait_impls = match tcx.trait_impls
-                                   .borrow()
-                                   .get(&coerce_unsized_trait)
-                                   .cloned() {
-            None => {
-                debug!("check_implementations_of_coerce_unsized(): no types \
-                        with implementations of `CoerceUnsized` found");
-                return
-            }
-            Some(found_impls) => found_impls
-        };
+        let trait_def = ty::lookup_trait_def(tcx, coerce_unsized_trait);
 
-        // Clone first to avoid a double borrow error.
-        let trait_impls = trait_impls.borrow().clone();
-
-        for &impl_did in &trait_impls {
+        trait_def.for_each_impl(tcx, |impl_did| {
             debug!("check_implementations_of_coerce_unsized: impl_did={}",
                    impl_did.repr(tcx));
 
             if impl_did.krate != ast::LOCAL_CRATE {
                 debug!("check_implementations_of_coerce_unsized(): impl not \
                         in this crate");
-                continue
+                return;
             }
 
-            let source = self.get_self_type_for_implementation(impl_did).ty;
+            let source = ty::lookup_item_type(tcx, impl_did).ty;
             let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
                                                      impl_did.node);
             let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
@@ -507,12 +495,12 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     if def_id_a != def_id_b {
                         let source_path = ty::item_path_str(tcx, def_id_a);
                         let target_path = ty::item_path_str(tcx, def_id_b);
-                        span_err!(tcx.sess, span, E0373,
+                        span_err!(tcx.sess, span, E0377,
                                   "the trait `CoerceUnsized` may only be implemented \
                                    for a coercion between structures with the same \
                                    definition; expected {}, found {}",
                                   source_path, target_path);
-                        continue;
+                        return;
                     }
 
                     let origin = infer::Misc(span);
@@ -532,7 +520,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                                   "the trait `CoerceUnsized` may only be implemented \
                                    for a coercion between structures with one field \
                                    being coerced, none found");
-                        continue;
+                        return;
                     } else if diff_fields.len() > 1 {
                         span_err!(tcx.sess, span, E0375,
                                   "the trait `CoerceUnsized` may only be implemented \
@@ -549,7 +537,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                                                 a.repr(tcx),
                                                 b.repr(tcx))
                                    }).collect::<Vec<_>>().connect(", "));
-                        continue;
+                        return;
                     }
 
                     let (i, a, b) = diff_fields[0];
@@ -561,7 +549,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     span_err!(tcx.sess, span, E0376,
                               "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures");
-                    continue;
+                    return;
                 }
             };
 
@@ -578,14 +566,15 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 traits::report_fulfillment_errors(&infcx, &errors);
             }
 
-            // Finally, resolve all regions. This catches wily misuses of lifetime
-            // parameters.
-            infcx.resolve_regions_and_report_errors(impl_did.node);
+            // Finally, resolve all regions.
+            let mut free_regions = FreeRegionMap::new();
+            free_regions.relate_free_regions_from_predicates(tcx, &param_env.caller_bounds);
+            infcx.resolve_regions_and_report_errors(&free_regions, impl_did.node);
 
             if let Some(kind) = kind {
                 tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind);
             }
-        }
+        });
     }
 }
 
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index c75a0d816a8..4c9fe6492e9 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -323,7 +323,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                     return;
                 }
                 if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() {
-                    span_err!(self.tcx.sess, item.span, E0323,
+                    span_err!(self.tcx.sess, item.span, E0328,
                               "explicit impls for the `Unsize` trait are not permitted");
                     return;
                 }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index ac10a4e7121..e92779641c9 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -452,13 +452,13 @@ register_diagnostics! {
     E0369, // binary operation `<op>` cannot be applied to types
     E0371, // impl Trait for Trait is illegal
     E0372, // impl Trait for Trait where Trait is not object safe
-    E0373, // the trait `CoerceUnsized` may only be implemented for a coercion
-           // between structures with the same definition
     E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with one field being coerced, none found
     E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with one field being coerced, but multiple
            // fields need coercions
-    E0376  // the trait `CoerceUnsized` may only be implemented for a coercion
+    E0376, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures
+    E0377  // the trait `CoerceUnsized` may only be implemented for a coercion
+           // between structures with the same definition
 }
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index febf5f1b183..f9ed7c863d1 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -531,15 +531,16 @@ mod tests {
         assert_eq!(*lock, 2);
     }
 
-    #[test]
-    fn test_mutex_unsized() {
-        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
-        {
-            let b = &mut *mutex.lock().unwrap();
-            b[0] = 4;
-            b[2] = 5;
-        }
-        let comp: &[i32] = &[4, 2, 5];
-        assert_eq!(&*mutex.lock().unwrap(), comp);
-    }
+    // FIXME(#25351) needs deeply nested coercions of DST structs.
+    // #[test]
+    // fn test_mutex_unsized() {
+    //     let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
+    //     {
+    //         let b = &mut *mutex.lock().unwrap();
+    //         b[0] = 4;
+    //         b[2] = 5;
+    //     }
+    //     let comp: &[i32] = &[4, 2, 5];
+    //     assert_eq!(&*mutex.lock().unwrap(), comp);
+    // }
 }
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 625377df7d6..36f6fbf3b72 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -573,17 +573,18 @@ mod tests {
         assert_eq!(*lock, 2);
     }
 
-    #[test]
-    fn test_rwlock_unsized() {
-        let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
-        {
-            let b = &mut *rw.write().unwrap();
-            b[0] = 4;
-            b[2] = 5;
-        }
-        let comp: &[i32] = &[4, 2, 5];
-        assert_eq!(&*rw.read().unwrap(), comp);
-    }
+    // FIXME(#25351) needs deeply nested coercions of DST structs.
+    // #[test]
+    // fn test_rwlock_unsized() {
+    //     let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
+    //     {
+    //         let b = &mut *rw.write().unwrap();
+    //         b[0] = 4;
+    //         b[2] = 5;
+    //     }
+    //     let comp: &[i32] = &[4, 2, 5];
+    //     assert_eq!(&*rw.read().unwrap(), comp);
+    // }
 
     #[test]
     fn test_rwlock_try_write() {
diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs
index 415785a1174..2099424b05c 100644
--- a/src/test/compile-fail/fat-ptr-cast.rs
+++ b/src/test/compile-fail/fat-ptr-cast.rs
@@ -16,8 +16,8 @@ fn main() {
     let a: &[i32] = &[1, 2, 3];
     let b: Box<[i32]> = Box::new([1, 2, 3]);
 
-    a as usize; //~ ERROR illegal cast
-    b as usize; //~ ERROR illegal cast
+    a as usize; //~ ERROR non-scalar cast
+    b as usize; //~ ERROR non-scalar cast
 
     let a: usize = 42;
     a as *const [i32]; //~ ERROR cast to fat pointer: `usize` as `*const [i32]`