1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Overlap: No two impls for the same trait are implemented for the
12 //! same type. Likewise, no two inherent impls for a given type
13 //! constructor provide a method with the same name.
16 use rustc::ty::{self, TyCtxt, TypeFoldable};
18 use rustc::dep_graph::DepNode;
20 use rustc::hir::itemlikevisit::ItemLikeVisitor;
22 pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
23 let mut overlap = OverlapChecker { tcx };
25 // this secondary walk specifically checks for some other cases,
26 // like defaulted traits, for which additional overlap rules exist
27 tcx.hir.krate().visit_all_item_likes(&mut overlap);
30 pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
31 let impl_def_id = tcx.hir.local_def_id(node_id);
32 let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
33 let trait_def_id = trait_ref.def_id;
35 if trait_ref.references_error() {
36 debug!("coherence: skipping impl {:?} with error {:?}",
37 impl_def_id, trait_ref);
42 tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id));
44 // Trigger building the specialization graph for the trait of this impl.
45 // This will detect any overlap errors.
46 tcx.specialization_graph_of(trait_def_id);
49 // check for overlap with the automatic `impl Trait for Trait`
50 if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
51 // This is something like impl Trait1 for Trait2. Illegal
52 // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
54 if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
55 // This is an error, but it will be reported by wfcheck. Ignore it here.
56 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
58 let mut supertrait_def_ids =
59 traits::supertrait_def_ids(tcx,
60 data.principal().unwrap().def_id());
61 if supertrait_def_ids.any(|d| d == trait_def_id) {
63 tcx.span_of_impl(impl_def_id).unwrap(),
65 "the object type `{}` automatically \
66 implements the trait `{}`",
68 tcx.item_path_str(trait_def_id));
74 struct OverlapChecker<'cx, 'tcx: 'cx> {
75 tcx: TyCtxt<'cx, 'tcx, 'tcx>,
78 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
79 fn visit_item(&mut self, item: &'v hir::Item) {
81 hir::ItemDefaultImpl(..) => {
82 // look for another default impl; note that due to the
83 // general orphan/coherence rules, it must always be
85 let impl_def_id = self.tcx.hir.local_def_id(item.id);
86 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
88 let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap();
89 if prev_id != item.id {
90 let mut err = struct_span_err!(self.tcx.sess,
91 self.tcx.span_of_impl(impl_def_id).unwrap(),
93 "redundant default implementations of trait \
96 err.span_note(self.tcx
97 .span_of_impl(self.tcx.hir.local_def_id(prev_id))
99 "redundant implementation is here:");
103 hir::ItemImpl(.., Some(_), _, _) => {
109 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
112 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {