]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/coherence/overlap.rs
383a9e0e69542caeadd47d406d3d3d76f90d69b5
[rust.git] / src / librustc_typeck / coherence / overlap.rs
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.
4 //
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.
10
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.
14
15 use rustc::traits;
16 use rustc::ty::{self, TyCtxt, TypeFoldable};
17 use syntax::ast;
18 use rustc::dep_graph::DepNode;
19 use rustc::hir;
20 use rustc::hir::itemlikevisit::ItemLikeVisitor;
21
22 pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
23     let mut overlap = OverlapChecker { tcx };
24
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);
28 }
29
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;
34
35     if trait_ref.references_error() {
36         debug!("coherence: skipping impl {:?} with error {:?}",
37                impl_def_id, trait_ref);
38         return
39     }
40
41     let _task =
42         tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id));
43
44     let def = tcx.trait_def(trait_def_id);
45
46     // attempt to insert into the specialization graph
47     let insert_result = def.add_impl_for_specialization(tcx, impl_def_id);
48
49     // insertion failed due to overlap
50     if let Err(overlap) = insert_result {
51         let mut err = struct_span_err!(tcx.sess,
52                                        tcx.span_of_impl(impl_def_id).unwrap(),
53                                        E0119,
54                                        "conflicting implementations of trait `{}`{}:",
55                                        overlap.trait_desc,
56                                        overlap.self_desc.clone().map_or(String::new(),
57                                                                         |ty| {
58             format!(" for type `{}`", ty)
59         }));
60
61         match tcx.span_of_impl(overlap.with_impl) {
62             Ok(span) => {
63                 err.span_label(span, &format!("first implementation here"));
64                 err.span_label(tcx.span_of_impl(impl_def_id).unwrap(),
65                                &format!("conflicting implementation{}",
66                                         overlap.self_desc
67                                             .map_or(String::new(),
68                                                     |ty| format!(" for `{}`", ty))));
69             }
70             Err(cname) => {
71                 err.note(&format!("conflicting implementation in crate `{}`", cname));
72             }
73         }
74
75         err.emit();
76     }
77
78     // check for overlap with the automatic `impl Trait for Trait`
79     if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
80         // This is something like impl Trait1 for Trait2. Illegal
81         // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
82
83         if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
84             // This is an error, but it will be reported by wfcheck.  Ignore it here.
85             // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
86         } else {
87             let mut supertrait_def_ids =
88                 traits::supertrait_def_ids(tcx,
89                                            data.principal().unwrap().def_id());
90             if supertrait_def_ids.any(|d| d == trait_def_id) {
91                 span_err!(tcx.sess,
92                           tcx.span_of_impl(impl_def_id).unwrap(),
93                           E0371,
94                           "the object type `{}` automatically \
95                            implements the trait `{}`",
96                           trait_ref.self_ty(),
97                           tcx.item_path_str(trait_def_id));
98             }
99         }
100     }
101 }
102
103 struct OverlapChecker<'cx, 'tcx: 'cx> {
104     tcx: TyCtxt<'cx, 'tcx, 'tcx>,
105 }
106
107 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
108     fn visit_item(&mut self, item: &'v hir::Item) {
109         match item.node {
110             hir::ItemDefaultImpl(..) => {
111                 // look for another default impl; note that due to the
112                 // general orphan/coherence rules, it must always be
113                 // in this crate.
114                 let impl_def_id = self.tcx.hir.local_def_id(item.id);
115                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
116
117                 let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap();
118                 if prev_id != item.id {
119                     let mut err = struct_span_err!(self.tcx.sess,
120                                                    self.tcx.span_of_impl(impl_def_id).unwrap(),
121                                                    E0521,
122                                                    "redundant default implementations of trait \
123                                                     `{}`:",
124                                                    trait_ref);
125                     err.span_note(self.tcx
126                                       .span_of_impl(self.tcx.hir.local_def_id(prev_id))
127                                       .unwrap(),
128                                   "redundant implementation is here:");
129                     err.emit();
130                 }
131             }
132             hir::ItemImpl(.., Some(_), _, _) => {
133             }
134             _ => {}
135         }
136     }
137
138     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
139     }
140
141     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
142     }
143 }