]> git.lizzy.rs Git - rust.git/commitdiff
coherence: move the builtin trait checks to their own module
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Sat, 3 Dec 2016 22:28:30 +0000 (00:28 +0200)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Tue, 3 Jan 2017 19:50:18 +0000 (21:50 +0200)
no functional changes

src/librustc_typeck/coherence/builtin.rs [new file with mode: 0644]
src/librustc_typeck/coherence/mod.rs

diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
new file mode 100644 (file)
index 0000000..6fde18d
--- /dev/null
@@ -0,0 +1,357 @@
+// Copyright 2016 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.
+
+//! Check properties that are required by built-in traits and set
+//! up data structures required by type-checking/translation.
+
+use rustc::middle::free_region::FreeRegionMap;
+use rustc::middle::lang_items::UnsizeTraitLangItem;
+
+use rustc::traits::{self, ObligationCause, Reveal};
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::ParameterEnvironment;
+use rustc::ty::TypeFoldable;
+use rustc::ty::subst::Subst;
+use rustc::ty::util::CopyImplementationError;
+use rustc::infer;
+
+use rustc::hir::map as hir_map;
+use rustc::hir::{self, ItemImpl};
+
+pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    populate_destructors(tcx);
+    check_implementations_of_copy(tcx);
+    check_implementations_of_coerce_unsized(tcx);
+}
+
+fn populate_destructors<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let drop_trait = match tcx.lang_items.drop_trait() {
+        Some(id) => id,
+        None => return,
+    };
+    tcx.populate_implementations_for_trait_if_necessary(drop_trait);
+    let drop_trait = tcx.lookup_trait_def(drop_trait);
+
+    drop_trait.for_each_impl(tcx, |impl_did| {
+        let items = tcx.associated_item_def_ids(impl_did);
+        if items.is_empty() {
+            // We'll error out later. For now, just don't ICE.
+            return;
+        }
+        let method_def_id = items[0];
+
+        let self_type = tcx.item_type(impl_did);
+        match self_type.sty {
+            ty::TyAdt(type_def, _) => {
+                type_def.set_destructor(method_def_id);
+            }
+            _ => {
+                // Destructors only work on nominal types.
+                if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) {
+                    match tcx.map.find(impl_node_id) {
+                        Some(hir_map::NodeItem(item)) => {
+                            let span = match item.node {
+                                ItemImpl(.., ref ty, _) => ty.span,
+                                _ => item.span,
+                            };
+                            struct_span_err!(tcx.sess,
+                                             span,
+                                             E0120,
+                                             "the Drop trait may only be implemented on \
+                                              structures")
+                                    .span_label(span,
+                                                &format!("implementing Drop requires a struct"))
+                                .emit();
+                        }
+                        _ => {
+                            bug!("didn't find impl in ast map");
+                        }
+                    }
+                } else {
+                    bug!("found external impl of Drop trait on \
+                          something other than a struct");
+                }
+            }
+        }
+    });
+}
+
+fn check_implementations_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let copy_trait = match tcx.lang_items.copy_trait() {
+        Some(id) => id,
+        None => return,
+    };
+    tcx.populate_implementations_for_trait_if_necessary(copy_trait);
+    let copy_trait = tcx.lookup_trait_def(copy_trait);
+
+    copy_trait.for_each_impl(tcx, |impl_did| {
+        debug!("check_implementations_of_copy: impl_did={:?}", impl_did);
+
+        let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) {
+            n
+        } else {
+            debug!("check_implementations_of_copy(): impl not in this \
+                    crate");
+            return;
+        };
+
+        let self_type = tcx.item_type(impl_did);
+        debug!("check_implementations_of_copy: self_type={:?} (bound)",
+               self_type);
+
+        let span = tcx.map.span(impl_node_id);
+        let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
+        let self_type = self_type.subst(tcx, &param_env.free_substs);
+        assert!(!self_type.has_escaping_regions());
+
+        debug!("check_implementations_of_copy: self_type={:?} (free)",
+               self_type);
+
+        match param_env.can_type_implement_copy(tcx, self_type, span) {
+            Ok(()) => {}
+            Err(CopyImplementationError::InfrigingField(name)) => {
+                struct_span_err!(tcx.sess,
+                                 span,
+                                 E0204,
+                                 "the trait `Copy` may not be implemented for this type")
+                    .span_label(span, &format!("field `{}` does not implement `Copy`", name))
+                    .emit()
+            }
+            Err(CopyImplementationError::InfrigingVariant(name)) => {
+                let item = tcx.map.expect_item(impl_node_id);
+                let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node {
+                    tr.path.span
+                } else {
+                    span
+                };
+
+                struct_span_err!(tcx.sess,
+                                 span,
+                                 E0205,
+                                 "the trait `Copy` may not be implemented for this type")
+                    .span_label(span,
+                                &format!("variant `{}` does not implement `Copy`", name))
+                    .emit()
+            }
+            Err(CopyImplementationError::NotAnAdt) => {
+                let item = tcx.map.expect_item(impl_node_id);
+                let span = if let ItemImpl(.., ref ty, _) = item.node {
+                    ty.span
+                } else {
+                    span
+                };
+
+                struct_span_err!(tcx.sess,
+                                 span,
+                                 E0206,
+                                 "the trait `Copy` may not be implemented for this type")
+                    .span_label(span, &format!("type is not a structure or enumeration"))
+                    .emit();
+            }
+            Err(CopyImplementationError::HasDestructor) => {
+                struct_span_err!(tcx.sess,
+                                 span,
+                                 E0184,
+                                 "the trait `Copy` may not be implemented for this type; the \
+                                  type has a destructor")
+                        .span_label(span, &format!("Copy not allowed on types with destructors"))
+                    .emit();
+            }
+        }
+    });
+}
+
+fn check_implementations_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let coerce_unsized_trait = match tcx.lang_items.coerce_unsized_trait() {
+        Some(id) => id,
+        None => return,
+    };
+    let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) {
+        Ok(id) => id,
+        Err(err) => {
+            tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
+        }
+    };
+
+    let trait_def = tcx.lookup_trait_def(coerce_unsized_trait);
+
+    trait_def.for_each_impl(tcx, |impl_did| {
+        debug!("check_implementations_of_coerce_unsized: impl_did={:?}",
+               impl_did);
+
+        let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) {
+            n
+        } else {
+            debug!("check_implementations_of_coerce_unsized(): impl not \
+                    in this crate");
+            return;
+        };
+
+        let source = tcx.item_type(impl_did);
+        let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+        let target = trait_ref.substs.type_at(1);
+        debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
+               source,
+               target);
+
+        let span = tcx.map.span(impl_node_id);
+        let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
+        let source = source.subst(tcx, &param_env.free_substs);
+        let target = target.subst(tcx, &param_env.free_substs);
+        assert!(!source.has_escaping_regions());
+
+        debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
+               source,
+               target);
+
+        tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| {
+            let cause = ObligationCause::misc(span, impl_node_id);
+            let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
+                               mt_b: ty::TypeAndMut<'tcx>,
+                               mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
+                if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
+                    infcx.report_mismatched_types(&cause,
+                                                  mk_ptr(mt_b.ty),
+                                                  target,
+                                                  ty::error::TypeError::Mutability)
+                         .emit();
+                }
+                (mt_a.ty, mt_b.ty, unsize_trait, None)
+            };
+            let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) {
+                (&ty::TyBox(a), &ty::TyBox(b)) => (a, b, unsize_trait, None),
+
+                (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
+                    infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
+                    check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
+                }
+
+                (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) |
+                (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
+                    check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
+                }
+
+                (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(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);
+                        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);
+                        return;
+                    }
+
+                    let fields = &def_a.struct_variant().fields;
+                    let diff_fields = fields.iter()
+                        .enumerate()
+                        .filter_map(|(i, f)| {
+                            let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
+
+                            if tcx.item_type(f.did).is_phantom_data() {
+                                // Ignore PhantomData fields
+                                return None;
+                            }
+
+                            // Ignore fields that aren't significantly changed
+                            if let Ok(ok) = infcx.sub_types(false, &cause, b, a) {
+                                if ok.obligations.is_empty() {
+                                    return None;
+                                }
+                            }
+
+                            // Collect up all fields that were significantly changed
+                            // i.e. those that contain T in coerce_unsized T -> U
+                            Some((i, a, b))
+                        })
+                        .collect::<Vec<_>>();
+
+                    if diff_fields.is_empty() {
+                        span_err!(tcx.sess,
+                                  span,
+                                  E0374,
+                                  "the trait `CoerceUnsized` may only be implemented \
+                                   for a coercion between structures with one field \
+                                   being coerced, none found");
+                        return;
+                    } else if diff_fields.len() > 1 {
+                        let item = tcx.map.expect_item(impl_node_id);
+                        let span = if let ItemImpl(.., Some(ref t), _, _) = item.node {
+                            t.path.span
+                        } else {
+                            tcx.map.span(impl_node_id)
+                        };
+
+                        let mut err = struct_span_err!(tcx.sess,
+                                                       span,
+                                                       E0375,
+                                                       "implementing the trait \
+                                                        `CoerceUnsized` requires multiple \
+                                                        coercions");
+                        err.note("`CoerceUnsized` may only be implemented for \
+                                  a coercion between structures with one field being coerced");
+                        err.note(&format!("currently, {} fields need coercions: {}",
+                                          diff_fields.len(),
+                                          diff_fields.iter()
+                                          .map(|&(i, a, b)| {
+                                              format!("{} ({} to {})", fields[i].name, a, b)
+                                          })
+                                          .collect::<Vec<_>>()
+                                          .join(", ")));
+                        err.span_label(span, &format!("requires multiple coercions"));
+                        err.emit();
+                        return;
+                    }
+
+                    let (i, a, b) = diff_fields[0];
+                    let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
+                    (a, b, coerce_unsized_trait, Some(kind))
+                }
+
+                _ => {
+                    span_err!(tcx.sess,
+                              span,
+                              E0376,
+                              "the trait `CoerceUnsized` may only be implemented \
+                               for a coercion between structures");
+                    return;
+                }
+            };
+
+            let mut fulfill_cx = traits::FulfillmentContext::new();
+
+            // Register an obligation for `A: Trait<B>`.
+            let cause = traits::ObligationCause::misc(span, impl_node_id);
+            let predicate =
+                tcx.predicate_for_trait_def(cause, trait_def_id, 0, source, &[target]);
+            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);
+            }
+
+            // Finally, resolve all regions.
+            let mut free_regions = FreeRegionMap::new();
+            free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
+                                                             .caller_bounds);
+            infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
+
+            if let Some(kind) = kind {
+                tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind);
+            }
+        });
+    });
+}
index 3bbe5aa1fef376272fd19e28e1f57ae5f4b741ae..3293818348a94e34375a707eb281ab0c32fc9d21 100644 (file)
 // mappings. That mapping code resides here.
 
 use hir::def_id::DefId;
-use middle::lang_items::UnsizeTraitLangItem;
-use rustc::ty::subst::Subst;
+use rustc::traits::Reveal;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc::traits::{self, ObligationCause, Reveal};
-use rustc::ty::ParameterEnvironment;
 use rustc::ty::{Ty, TyBool, TyChar, TyError};
 use rustc::ty::{TyParam, TyRawPtr};
 use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
 use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
 use rustc::ty::{TyProjection, TyAnon};
-use rustc::ty::util::CopyImplementationError;
-use middle::free_region::FreeRegionMap;
 use CrateCtxt;
-use rustc::infer::{self, InferCtxt};
+use rustc::infer::{InferCtxt};
 use syntax_pos::Span;
 use rustc::dep_graph::DepNode;
-use rustc::hir::map as hir_map;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::{Item, ItemImpl};
 use rustc::hir;
 
+mod builtin;
 mod orphan;
 mod overlap;
 mod unsafety;
@@ -96,18 +91,7 @@ fn check(&self) {
         self.crate_context.tcx.visit_all_item_likes_in_krate(
             DepNode::CoherenceCheckImpl,
             &mut CoherenceCheckVisitor { cc: self });
-
-        // Populate the table of destructors. It might seem a bit strange to
-        // do this here, but it's actually the most convenient place, since
-        // the coherence tables contain the trait -> type mappings.
-        self.populate_destructors();
-
-        // Check to make sure implementations of `Copy` are legal.
-        self.check_implementations_of_copy();
-
-        // Check to make sure implementations of `CoerceUnsized` are legal
-        // and collect the necessary information from them.
-        self.check_implementations_of_coerce_unsized();
+        builtin::check(self.crate_context.tcx);
     }
 
     fn check_implementation(&self, item: &Item) {
@@ -161,338 +145,6 @@ fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'gcx>, impl_def_id: DefId)
         let trait_def = self.crate_context.tcx.lookup_trait_def(impl_trait_ref.def_id);
         trait_def.record_local_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref);
     }
-
-    // Destructors
-    //
-
-    fn populate_destructors(&self) {
-        let tcx = self.crate_context.tcx;
-        let drop_trait = match tcx.lang_items.drop_trait() {
-            Some(id) => id,
-            None => return,
-        };
-        tcx.populate_implementations_for_trait_if_necessary(drop_trait);
-        let drop_trait = tcx.lookup_trait_def(drop_trait);
-
-        drop_trait.for_each_impl(tcx, |impl_did| {
-            let items = tcx.associated_item_def_ids(impl_did);
-            if items.is_empty() {
-                // We'll error out later. For now, just don't ICE.
-                return;
-            }
-            let method_def_id = items[0];
-
-            let self_type = tcx.item_type(impl_did);
-            match self_type.sty {
-                ty::TyAdt(type_def, _) => {
-                    type_def.set_destructor(method_def_id);
-                }
-                _ => {
-                    // Destructors only work on nominal types.
-                    if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) {
-                        match tcx.map.find(impl_node_id) {
-                            Some(hir_map::NodeItem(item)) => {
-                                let span = match item.node {
-                                    ItemImpl(.., ref ty, _) => ty.span,
-                                    _ => item.span,
-                                };
-                                struct_span_err!(tcx.sess,
-                                                 span,
-                                                 E0120,
-                                                 "the Drop trait may only be implemented on \
-                                                  structures")
-                                    .span_label(span,
-                                                &format!("implementing Drop requires a struct"))
-                                    .emit();
-                            }
-                            _ => {
-                                bug!("didn't find impl in ast map");
-                            }
-                        }
-                    } else {
-                        bug!("found external impl of Drop trait on \
-                              something other than a struct");
-                    }
-                }
-            }
-        });
-    }
-
-    /// Ensures that implementations of the built-in trait `Copy` are legal.
-    fn check_implementations_of_copy(&self) {
-        let tcx = self.crate_context.tcx;
-        let copy_trait = match tcx.lang_items.copy_trait() {
-            Some(id) => id,
-            None => return,
-        };
-        tcx.populate_implementations_for_trait_if_necessary(copy_trait);
-        let copy_trait = tcx.lookup_trait_def(copy_trait);
-
-        copy_trait.for_each_impl(tcx, |impl_did| {
-            debug!("check_implementations_of_copy: impl_did={:?}", impl_did);
-
-            let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) {
-                n
-            } else {
-                debug!("check_implementations_of_copy(): impl not in this \
-                        crate");
-                return;
-            };
-
-            let self_type = tcx.item_type(impl_did);
-            debug!("check_implementations_of_copy: self_type={:?} (bound)",
-                   self_type);
-
-            let span = tcx.map.span(impl_node_id);
-            let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
-            let self_type = self_type.subst(tcx, &param_env.free_substs);
-            assert!(!self_type.has_escaping_regions());
-
-            debug!("check_implementations_of_copy: self_type={:?} (free)",
-                   self_type);
-
-            match param_env.can_type_implement_copy(tcx, self_type, span) {
-                Ok(()) => {}
-                Err(CopyImplementationError::InfrigingField(name)) => {
-                    struct_span_err!(tcx.sess,
-                                     span,
-                                     E0204,
-                                     "the trait `Copy` may not be implemented for this type")
-                        .span_label(span, &format!("field `{}` does not implement `Copy`", name))
-                        .emit()
-                }
-                Err(CopyImplementationError::InfrigingVariant(name)) => {
-                    let item = tcx.map.expect_item(impl_node_id);
-                    let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node {
-                        tr.path.span
-                    } else {
-                        span
-                    };
-
-                    struct_span_err!(tcx.sess,
-                                     span,
-                                     E0205,
-                                     "the trait `Copy` may not be implemented for this type")
-                        .span_label(span,
-                                    &format!("variant `{}` does not implement `Copy`", name))
-                        .emit()
-                }
-                Err(CopyImplementationError::NotAnAdt) => {
-                    let item = tcx.map.expect_item(impl_node_id);
-                    let span = if let ItemImpl(.., ref ty, _) = item.node {
-                        ty.span
-                    } else {
-                        span
-                    };
-
-                    struct_span_err!(tcx.sess,
-                                     span,
-                                     E0206,
-                                     "the trait `Copy` may not be implemented for this type")
-                        .span_label(span, &format!("type is not a structure or enumeration"))
-                        .emit();
-                }
-                Err(CopyImplementationError::HasDestructor) => {
-                    struct_span_err!(tcx.sess,
-                                     span,
-                                     E0184,
-                                     "the trait `Copy` may not be implemented for this type; the \
-                                      type has a destructor")
-                        .span_label(span, &format!("Copy not allowed on types with destructors"))
-                        .emit();
-                }
-            }
-        });
-    }
-
-    /// Process implementations of the built-in trait `CoerceUnsized`.
-    fn check_implementations_of_coerce_unsized(&self) {
-        let tcx = self.crate_context.tcx;
-        let coerce_unsized_trait = match tcx.lang_items.coerce_unsized_trait() {
-            Some(id) => id,
-            None => return,
-        };
-        let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) {
-            Ok(id) => id,
-            Err(err) => {
-                tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
-            }
-        };
-
-        let trait_def = tcx.lookup_trait_def(coerce_unsized_trait);
-
-        trait_def.for_each_impl(tcx, |impl_did| {
-            debug!("check_implementations_of_coerce_unsized: impl_did={:?}",
-                   impl_did);
-
-            let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) {
-                n
-            } else {
-                debug!("check_implementations_of_coerce_unsized(): impl not \
-                        in this crate");
-                return;
-            };
-
-            let source = tcx.item_type(impl_did);
-            let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap();
-            let target = trait_ref.substs.type_at(1);
-            debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
-                   source,
-                   target);
-
-            let span = tcx.map.span(impl_node_id);
-            let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
-            let source = source.subst(tcx, &param_env.free_substs);
-            let target = target.subst(tcx, &param_env.free_substs);
-            assert!(!source.has_escaping_regions());
-
-            debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
-                   source,
-                   target);
-
-            tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| {
-                let cause = ObligationCause::misc(span, impl_node_id);
-                let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>,
-                                   mt_b: ty::TypeAndMut<'gcx>,
-                                   mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| {
-                    if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
-                        infcx.report_mismatched_types(&cause,
-                                                      mk_ptr(mt_b.ty),
-                                                      target,
-                                                      ty::error::TypeError::Mutability).emit();
-                    }
-                    (mt_a.ty, mt_b.ty, unsize_trait, None)
-                };
-                let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) {
-                    (&ty::TyBox(a), &ty::TyBox(b)) => (a, b, unsize_trait, None),
-
-                    (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
-                        infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
-                        check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
-                    }
-
-                    (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) |
-                    (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
-                        check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
-                    }
-
-                    (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(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);
-                            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);
-                            return;
-                        }
-
-                        let fields = &def_a.struct_variant().fields;
-                        let diff_fields = fields.iter()
-                            .enumerate()
-                            .filter_map(|(i, f)| {
-                                let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
-
-                                if tcx.item_type(f.did).is_phantom_data() {
-                                    // Ignore PhantomData fields
-                                    return None;
-                                }
-
-                                // Ignore fields that aren't significantly changed
-                                if let Ok(ok) = infcx.sub_types(false, &cause, b, a) {
-                                    if ok.obligations.is_empty() {
-                                        return None;
-                                    }
-                                }
-
-                                // Collect up all fields that were significantly changed
-                                // i.e. those that contain T in coerce_unsized T -> U
-                                Some((i, a, b))
-                            })
-                            .collect::<Vec<_>>();
-
-                        if diff_fields.is_empty() {
-                            span_err!(tcx.sess,
-                                      span,
-                                      E0374,
-                                      "the trait `CoerceUnsized` may only be implemented \
-                                       for a coercion between structures with one field \
-                                       being coerced, none found");
-                            return;
-                        } else if diff_fields.len() > 1 {
-                            let item = tcx.map.expect_item(impl_node_id);
-                            let span = if let ItemImpl(.., Some(ref t), _, _) = item.node {
-                                t.path.span
-                            } else {
-                                tcx.map.span(impl_node_id)
-                            };
-
-                            let mut err = struct_span_err!(tcx.sess,
-                                                           span,
-                                                           E0375,
-                                                           "implementing the trait \
-                                                            `CoerceUnsized` requires multiple \
-                                                            coercions");
-                            err.note("`CoerceUnsized` may only be implemented for \
-                                      a coercion between structures with one field being coerced");
-                            err.note(&format!("currently, {} fields need coercions: {}",
-                                              diff_fields.len(),
-                                              diff_fields.iter()
-                                                  .map(|&(i, a, b)| {
-                                                      format!("{} ({} to {})", fields[i].name, a, b)
-                                                  })
-                                                  .collect::<Vec<_>>()
-                                                  .join(", ")));
-                            err.span_label(span, &format!("requires multiple coercions"));
-                            err.emit();
-                            return;
-                        }
-
-                        let (i, a, b) = diff_fields[0];
-                        let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
-                        (a, b, coerce_unsized_trait, Some(kind))
-                    }
-
-                    _ => {
-                        span_err!(tcx.sess,
-                                  span,
-                                  E0376,
-                                  "the trait `CoerceUnsized` may only be implemented \
-                                   for a coercion between structures");
-                        return;
-                    }
-                };
-
-                let mut fulfill_cx = traits::FulfillmentContext::new();
-
-                // Register an obligation for `A: Trait<B>`.
-                let cause = traits::ObligationCause::misc(span, impl_node_id);
-                let predicate =
-                    tcx.predicate_for_trait_def(cause, trait_def_id, 0, source, &[target]);
-                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);
-                }
-
-                // Finally, resolve all regions.
-                let mut free_regions = FreeRegionMap::new();
-                free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
-                    .caller_bounds);
-                infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
-
-                if let Some(kind) = kind {
-                    tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind);
-                }
-            });
-        });
-    }
 }
 
 fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) {