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, ProjectionMode};
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 { tcx: tcx,
27 default_impls: DefIdMap() };
29 // this secondary walk specifically checks for some other cases,
30 // like defaulted traits, for which additional overlap rules exist
31 tcx.visit_all_items_in_krate(DepNode::CoherenceOverlapCheckSpecial, &mut overlap);
34 struct OverlapChecker<'cx, 'tcx:'cx> {
35 tcx: TyCtxt<'cx, 'tcx, 'tcx>,
37 // maps from a trait def-id to an impl id
38 default_impls: DefIdMap<ast::NodeId>,
41 impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
42 fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
43 #[derive(Copy, Clone, PartialEq)]
44 enum Namespace { Type, Value }
46 fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
47 item: &ty::ImplOrTraitItemId)
48 -> (ast::Name, Namespace)
50 let name = tcx.impl_or_trait_item(item.def_id()).name();
52 ty::TypeTraitItemId(..) => Namespace::Type,
53 ty::ConstTraitItemId(..) => Namespace::Value,
54 ty::MethodTraitItemId(..) => Namespace::Value,
58 let impl_items = self.tcx.impl_items.borrow();
60 for item1 in &impl_items[&impl1] {
61 let (name, namespace) = name_and_namespace(self.tcx, item1);
63 for item2 in &impl_items[&impl2] {
64 if (name, namespace) == name_and_namespace(self.tcx, item2) {
65 let msg = format!("duplicate definitions with name `{}`", name);
66 let node_id = self.tcx.map.as_local_node_id(item1.def_id()).unwrap();
67 self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
69 self.tcx.span_of_impl(item1.def_id()).unwrap(),
76 fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
77 let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id));
79 let inherent_impls = self.tcx.inherent_impls.borrow();
80 let impls = match inherent_impls.get(&ty_def_id) {
85 for (i, &impl1_def_id) in impls.iter().enumerate() {
86 for &impl2_def_id in &impls[(i+1)..] {
87 self.tcx.infer_ctxt(None, None, ProjectionMode::Topmost).enter(|infcx| {
88 if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
89 self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
97 impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
98 fn visit_item(&mut self, item: &'v hir::Item) {
100 hir::ItemEnum(..) | hir::ItemStruct(..) => {
101 let type_def_id = self.tcx.map.local_def_id(item.id);
102 self.check_for_overlapping_inherent_impls(type_def_id);
105 hir::ItemDefaultImpl(..) => {
106 // look for another default impl; note that due to the
107 // general orphan/coherence rules, it must always be
109 let impl_def_id = self.tcx.map.local_def_id(item.id);
110 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
112 let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id);
113 if let Some(prev_id) = prev_default_impl {
114 let mut err = struct_span_err!(
116 self.tcx.span_of_impl(impl_def_id).unwrap(), E0521,
117 "redundant default implementations of trait `{}`:",
119 err.span_note(self.tcx.span_of_impl(self.tcx.map.local_def_id(prev_id))
121 "redundant implementation is here:");
125 hir::ItemImpl(_, _, _, Some(_), _, _) => {
126 let impl_def_id = self.tcx.map.local_def_id(item.id);
127 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
128 let trait_def_id = trait_ref.def_id;
130 let _task = self.tcx.dep_graph.in_task(
131 DepNode::CoherenceOverlapCheck(trait_def_id));
133 let def = self.tcx.lookup_trait_def(trait_def_id);
135 // attempt to insert into the specialization graph
136 let insert_result = def.add_impl_for_specialization(self.tcx, impl_def_id);
138 // insertion failed due to overlap
139 if let Err(overlap) = insert_result {
140 let mut err = struct_span_err!(
141 self.tcx.sess, self.tcx.span_of_impl(impl_def_id).unwrap(), E0119,
142 "conflicting implementations of trait `{}`{}:",
144 overlap.self_desc.clone().map_or(String::new(),
145 |ty| format!(" for type `{}`", ty)));
147 match self.tcx.span_of_impl(overlap.with_impl) {
150 &format!("first implementation here"));
151 err.span_label(self.tcx.span_of_impl(impl_def_id).unwrap(),
152 &format!("conflicting implementation{}",
154 .map_or(String::new(),
155 |ty| format!(" for `{}`", ty))));
158 err.note(&format!("conflicting implementation in crate `{}`",
166 // check for overlap with the automatic `impl Trait for Trait`
167 if let ty::TyTrait(ref data) = trait_ref.self_ty().sty {
168 // This is something like impl Trait1 for Trait2. Illegal
169 // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
171 if !self.tcx.is_object_safe(data.principal_def_id()) {
172 // This is an error, but it will be
173 // reported by wfcheck. Ignore it
174 // here. This is tested by
175 // `coherence-impl-trait-for-trait-object-safe.rs`.
177 let mut supertrait_def_ids =
178 traits::supertrait_def_ids(self.tcx, data.principal_def_id());
179 if supertrait_def_ids.any(|d| d == trait_def_id) {
180 span_err!(self.tcx.sess, item.span, E0371,
181 "the object type `{}` automatically \
182 implements the trait `{}`",
184 self.tcx.item_path_str(trait_def_id));