]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/coherence/overlap.rs
doc: remove incomplete sentence
[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.
13
14 use middle::traits;
15 use middle::ty;
16 use middle::infer::{mod, new_infer_ctxt};
17 use syntax::ast::{DefId};
18 use syntax::ast::{LOCAL_CRATE};
19 use syntax::ast;
20 use syntax::codemap::{Span};
21 use util::ppaux::Repr;
22
23 pub fn check(tcx: &ty::ctxt) {
24     let overlap = OverlapChecker { tcx: tcx };
25     overlap.check_for_overlapping_impls();
26 }
27
28 struct OverlapChecker<'cx, 'tcx:'cx> {
29     tcx: &'cx ty::ctxt<'tcx>
30 }
31
32 impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
33     fn check_for_overlapping_impls(&self) {
34         debug!("check_for_overlapping_impls");
35
36         // Collect this into a vector to avoid holding the
37         // refcell-lock during the
38         // check_for_overlapping_impls_of_trait() check, since that
39         // check can populate this table further with impls from other
40         // crates.
41         let trait_def_ids: Vec<ast::DefId> =
42             self.tcx.trait_impls.borrow().keys().map(|&d| d).collect();
43
44         for trait_def_id in trait_def_ids.iter() {
45             self.check_for_overlapping_impls_of_trait(*trait_def_id);
46         }
47     }
48
49     fn check_for_overlapping_impls_of_trait(&self,
50                                             trait_def_id: ast::DefId)
51     {
52         debug!("check_for_overlapping_impls_of_trait(trait_def_id={})",
53                trait_def_id.repr(self.tcx));
54
55         // FIXME -- it seems like this method actually pushes
56         // duplicate impls onto the list
57         ty::populate_implementations_for_trait_if_necessary(self.tcx,
58                                                             trait_def_id);
59
60         let mut impls = Vec::new();
61         self.push_impls_of_trait(trait_def_id, &mut impls);
62
63         for (i, &impl1_def_id) in impls.iter().enumerate() {
64             if impl1_def_id.krate != ast::LOCAL_CRATE {
65                 // we don't need to check impls if both are external;
66                 // that's the other crate's job.
67                 continue;
68             }
69
70             for &impl2_def_id in impls.slice_from(i+1).iter() {
71                 self.check_if_impls_overlap(trait_def_id,
72                                             impl1_def_id,
73                                             impl2_def_id);
74             }
75         }
76     }
77
78     fn check_if_impls_overlap(&self,
79                               trait_def_id: ast::DefId,
80                               impl1_def_id: ast::DefId,
81                               impl2_def_id: ast::DefId)
82     {
83         assert_eq!(impl1_def_id.krate, ast::LOCAL_CRATE);
84
85         debug!("check_if_impls_overlap({}, {}, {})",
86                trait_def_id.repr(self.tcx),
87                impl1_def_id.repr(self.tcx),
88                impl2_def_id.repr(self.tcx));
89
90         let infcx = infer::new_infer_ctxt(self.tcx);
91         if !traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
92             return;
93         }
94
95         span_err!(self.tcx.sess, self.span_of_impl(impl1_def_id), E0119,
96                   "conflicting implementations for trait `{}`",
97                   ty::item_path_str(self.tcx, trait_def_id));
98
99         if impl2_def_id.krate == ast::LOCAL_CRATE {
100             span_note!(self.tcx.sess, self.span_of_impl(impl2_def_id),
101                        "note conflicting implementation here");
102         } else {
103             let crate_store = &self.tcx.sess.cstore;
104             let cdata = crate_store.get_crate_data(impl2_def_id.krate);
105             span_note!(self.tcx.sess, self.span_of_impl(impl1_def_id),
106                        "conflicting implementation in crate `{}`",
107                        cdata.name);
108         }
109     }
110
111     fn push_impls_of_trait(&self,
112                            trait_def_id: ast::DefId,
113                            out: &mut Vec<ast::DefId>) {
114         match self.tcx.trait_impls.borrow().get(&trait_def_id) {
115             Some(impls) => { out.push_all(impls.borrow().as_slice()); }
116             None => { /* no impls */ }
117         }
118     }
119
120     fn span_of_impl(&self, impl_did: ast::DefId) -> Span {
121         assert_eq!(impl_did.krate, ast::LOCAL_CRATE);
122         self.tcx.map.span(impl_did.node)
123     }
124 }