1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use middle::traits;
use middle::ty;
use middle::infer::{mod, new_infer_ctxt};
use syntax::ast::{DefId};
use syntax::ast::{LOCAL_CRATE};
use syntax::ast;
use syntax::codemap::{Span};
use util::ppaux::Repr;
pub fn check(tcx: &ty::ctxt) {
let overlap = OverlapChecker { tcx: tcx };
overlap.check_for_overlapping_impls();
}
struct OverlapChecker<'cx, 'tcx:'cx> {
tcx: &'cx ty::ctxt<'tcx>
}
impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
fn check_for_overlapping_impls(&self) {
debug!("check_for_overlapping_impls");
let trait_def_ids: Vec<ast::DefId> =
self.tcx.trait_impls.borrow().keys().map(|&d| d).collect();
for trait_def_id in trait_def_ids.iter() {
self.check_for_overlapping_impls_of_trait(*trait_def_id);
}
}
fn check_for_overlapping_impls_of_trait(&self,
trait_def_id: ast::DefId)
{
debug!("check_for_overlapping_impls_of_trait(trait_def_id={})",
trait_def_id.repr(self.tcx));
ty::populate_implementations_for_trait_if_necessary(self.tcx,
trait_def_id);
let mut impls = Vec::new();
self.push_impls_of_trait(trait_def_id, &mut impls);
for (i, &impl1_def_id) in impls.iter().enumerate() {
if impl1_def_id.krate != ast::LOCAL_CRATE {
continue;
}
for &impl2_def_id in impls.slice_from(i+1).iter() {
self.check_if_impls_overlap(trait_def_id,
impl1_def_id,
impl2_def_id);
}
}
}
fn check_if_impls_overlap(&self,
trait_def_id: ast::DefId,
impl1_def_id: ast::DefId,
impl2_def_id: ast::DefId)
{
assert_eq!(impl1_def_id.krate, ast::LOCAL_CRATE);
debug!("check_if_impls_overlap({}, {}, {})",
trait_def_id.repr(self.tcx),
impl1_def_id.repr(self.tcx),
impl2_def_id.repr(self.tcx));
let infcx = infer::new_infer_ctxt(self.tcx);
if !traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
return;
}
span_err!(self.tcx.sess, self.span_of_impl(impl1_def_id), E0119,
"conflicting implementations for trait `{}`",
ty::item_path_str(self.tcx, trait_def_id));
if impl2_def_id.krate == ast::LOCAL_CRATE {
span_note!(self.tcx.sess, self.span_of_impl(impl2_def_id),
"note conflicting implementation here");
} else {
let crate_store = &self.tcx.sess.cstore;
let cdata = crate_store.get_crate_data(impl2_def_id.krate);
span_note!(self.tcx.sess, self.span_of_impl(impl1_def_id),
"conflicting implementation in crate `{}`",
cdata.name);
}
}
fn push_impls_of_trait(&self,
trait_def_id: ast::DefId,
out: &mut Vec<ast::DefId>) {
match self.tcx.trait_impls.borrow().get(&trait_def_id) {
Some(impls) => { out.push_all(impls.borrow().as_slice()); }
None => { }
}
}
fn span_of_impl(&self, impl_did: ast::DefId) -> Span {
assert_eq!(impl_did.krate, ast::LOCAL_CRATE);
self.tcx.map.span(impl_did.node)
}
}