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.
15 use hir
::def_id
::DefId
;
16 use rustc
::traits
::{self, Reveal}
;
17 use rustc
::ty
::{self, TyCtxt}
;
19 use rustc
::dep_graph
::DepNode
;
21 use rustc
::hir
::intravisit
;
22 use util
::nodemap
::DefIdMap
;
25 pub fn check
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) {
26 let mut overlap
= OverlapChecker
{
28 default_impls
: DefIdMap(),
31 // this secondary walk specifically checks for some other cases,
32 // like defaulted traits, for which additional overlap rules exist
33 tcx
.visit_all_items_in_krate(DepNode
::CoherenceOverlapCheckSpecial
, &mut overlap
);
36 struct OverlapChecker
<'cx
, 'tcx
: 'cx
> {
37 tcx
: TyCtxt
<'cx
, 'tcx
, 'tcx
>,
39 // maps from a trait def-id to an impl id
40 default_impls
: DefIdMap
<ast
::NodeId
>,
43 impl<'cx
, 'tcx
> OverlapChecker
<'cx
, 'tcx
> {
44 fn check_for_common_items_in_impls(&self, impl1
: DefId
, impl2
: DefId
) {
45 #[derive(Copy, Clone, PartialEq)]
51 fn name_and_namespace
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
53 -> (ast
::Name
, Namespace
) {
54 let item
= tcx
.impl_or_trait_item(def_id
);
57 ty
::TypeTraitItem(..) => Namespace
::Type
,
58 ty
::ConstTraitItem(..) => Namespace
::Value
,
59 ty
::MethodTraitItem(..) => Namespace
::Value
,
63 let impl_items
= self.tcx
.impl_or_trait_item_def_ids
.borrow();
65 for &item1
in &impl_items
[&impl1
][..] {
66 let (name
, namespace
) = name_and_namespace(self.tcx
, item1
);
68 for &item2
in &impl_items
[&impl2
][..] {
69 if (name
, namespace
) == name_and_namespace(self.tcx
, item2
) {
70 let msg
= format
!("duplicate definitions with name `{}`", name
);
71 let node_id
= self.tcx
.map
.as_local_node_id(item1
).unwrap();
72 self.tcx
.sess
.add_lint(lint
::builtin
::OVERLAPPING_INHERENT_IMPLS
,
74 self.tcx
.span_of_impl(item1
).unwrap(),
81 fn check_for_overlapping_inherent_impls(&self, ty_def_id
: DefId
) {
82 let _task
= self.tcx
.dep_graph
.in_task(DepNode
::CoherenceOverlapInherentCheck(ty_def_id
));
84 let inherent_impls
= self.tcx
.inherent_impls
.borrow();
85 let impls
= match inherent_impls
.get(&ty_def_id
) {
90 for (i
, &impl1_def_id
) in impls
.iter().enumerate() {
91 for &impl2_def_id
in &impls
[(i
+ 1)..] {
92 self.tcx
.infer_ctxt(None
, None
, Reveal
::ExactMatch
).enter(|infcx
| {
93 if traits
::overlapping_impls(&infcx
, impl1_def_id
, impl2_def_id
).is_some() {
94 self.check_for_common_items_in_impls(impl1_def_id
, impl2_def_id
)
102 impl<'cx
, 'tcx
, 'v
> intravisit
::Visitor
<'v
> for OverlapChecker
<'cx
, 'tcx
> {
103 fn visit_item(&mut self, item
: &'v hir
::Item
) {
106 hir
::ItemStruct(..) |
107 hir
::ItemUnion(..) => {
108 let type_def_id
= self.tcx
.map
.local_def_id(item
.id
);
109 self.check_for_overlapping_inherent_impls(type_def_id
);
112 hir
::ItemDefaultImpl(..) => {
113 // look for another default impl; note that due to the
114 // general orphan/coherence rules, it must always be
116 let impl_def_id
= self.tcx
.map
.local_def_id(item
.id
);
117 let trait_ref
= self.tcx
.impl_trait_ref(impl_def_id
).unwrap();
119 let prev_default_impl
= self.default_impls
.insert(trait_ref
.def_id
, item
.id
);
120 if let Some(prev_id
) = prev_default_impl
{
121 let mut err
= struct_span_err
!(self.tcx
.sess
,
122 self.tcx
.span_of_impl(impl_def_id
).unwrap(),
124 "redundant default implementations of trait \
127 err
.span_note(self.tcx
128 .span_of_impl(self.tcx
.map
.local_def_id(prev_id
))
130 "redundant implementation is here:");
134 hir
::ItemImpl(.., Some(_
), _
, _
) => {
135 let impl_def_id
= self.tcx
.map
.local_def_id(item
.id
);
136 let trait_ref
= self.tcx
.impl_trait_ref(impl_def_id
).unwrap();
137 let trait_def_id
= trait_ref
.def_id
;
140 self.tcx
.dep_graph
.in_task(DepNode
::CoherenceOverlapCheck(trait_def_id
));
142 let def
= self.tcx
.lookup_trait_def(trait_def_id
);
144 // attempt to insert into the specialization graph
145 let insert_result
= def
.add_impl_for_specialization(self.tcx
, impl_def_id
);
147 // insertion failed due to overlap
148 if let Err(overlap
) = insert_result
{
149 let mut err
= struct_span_err
!(self.tcx
.sess
,
150 self.tcx
.span_of_impl(impl_def_id
).unwrap(),
152 "conflicting implementations of trait `{}`{}:",
154 overlap
.self_desc
.clone().map_or(String
::new(),
156 format
!(" for type `{}`", ty
)
159 match self.tcx
.span_of_impl(overlap
.with_impl
) {
161 err
.span_label(span
, &format
!("first implementation here"));
162 err
.span_label(self.tcx
.span_of_impl(impl_def_id
).unwrap(),
163 &format
!("conflicting implementation{}",
165 .map_or(String
::new(),
166 |ty
| format
!(" for `{}`", ty
))));
169 err
.note(&format
!("conflicting implementation in crate `{}`", cname
));
176 // check for overlap with the automatic `impl Trait for Trait`
177 if let ty
::TyTrait(ref data
) = trait_ref
.self_ty().sty
{
178 // This is something like impl Trait1 for Trait2. Illegal
179 // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
181 if !self.tcx
.is_object_safe(data
.principal
.def_id()) {
182 // This is an error, but it will be
183 // reported by wfcheck. Ignore it
184 // here. This is tested by
185 // `coherence-impl-trait-for-trait-object-safe.rs`.
187 let mut supertrait_def_ids
=
188 traits
::supertrait_def_ids(self.tcx
, data
.principal
.def_id());
189 if supertrait_def_ids
.any(|d
| d
== trait_def_id
) {
190 span_err
!(self.tcx
.sess
,
193 "the object type `{}` automatically \
194 implements the trait `{}`",
196 self.tcx
.item_path_str(trait_def_id
));