]> git.proxmox.com Git - rustc.git/blob - src/librustc_typeck/coherence/inherent_impls_overlap.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_typeck / coherence / inherent_impls_overlap.rs
1 use crate::namespace::Namespace;
2 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
3 use rustc::hir;
4 use rustc::hir::itemlikevisit::ItemLikeVisitor;
5 use rustc::traits::{self, IntercrateMode};
6 use rustc::ty::TyCtxt;
7
8 use rustc_error_codes::*;
9
10 pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
11 assert_eq!(crate_num, LOCAL_CRATE);
12 let krate = tcx.hir().krate();
13 krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
14 }
15
16 struct InherentOverlapChecker<'tcx> {
17 tcx: TyCtxt<'tcx>,
18 }
19
20 impl InherentOverlapChecker<'tcx> {
21 fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
22 overlap: traits::OverlapResult<'_>) {
23
24 let name_and_namespace = |def_id| {
25 let item = self.tcx.associated_item(def_id);
26 (item.ident.modern(), Namespace::from(item.kind))
27 };
28
29 let impl_items1 = self.tcx.associated_item_def_ids(impl1);
30 let impl_items2 = self.tcx.associated_item_def_ids(impl2);
31
32 for &item1 in &impl_items1[..] {
33 let (name, namespace) = name_and_namespace(item1);
34
35 for &item2 in &impl_items2[..] {
36 if (name, namespace) == name_and_namespace(item2) {
37 let mut err =
38 struct_span_err!(self.tcx.sess,
39 self.tcx.span_of_impl(item1).unwrap(),
40 E0592,
41 "duplicate definitions with name `{}`",
42 name);
43 err.span_label(self.tcx.span_of_impl(item1).unwrap(),
44 format!("duplicate definitions for `{}`", name));
45 err.span_label(self.tcx.span_of_impl(item2).unwrap(),
46 format!("other definition for `{}`", name));
47
48 for cause in &overlap.intercrate_ambiguity_causes {
49 cause.add_intercrate_ambiguity_hint(&mut err);
50 }
51
52 if overlap.involves_placeholder {
53 traits::add_placeholder_note(&mut err);
54 }
55
56 err.emit();
57 }
58 }
59 }
60 }
61
62 fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
63 let impls = self.tcx.inherent_impls(ty_def_id);
64
65 for (i, &impl1_def_id) in impls.iter().enumerate() {
66 for &impl2_def_id in &impls[(i + 1)..] {
67 traits::overlapping_impls(
68 self.tcx,
69 impl1_def_id,
70 impl2_def_id,
71 IntercrateMode::Issue43355,
72 |overlap| {
73 self.check_for_common_items_in_impls(
74 impl1_def_id,
75 impl2_def_id,
76 overlap,
77 );
78 false
79 },
80 || true,
81 );
82 }
83 }
84 }
85 }
86
87 impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
88 fn visit_item(&mut self, item: &'v hir::Item) {
89 match item.kind {
90 hir::ItemKind::Enum(..) |
91 hir::ItemKind::Struct(..) |
92 hir::ItemKind::Trait(..) |
93 hir::ItemKind::Union(..) => {
94 let type_def_id = self.tcx.hir().local_def_id(item.hir_id);
95 self.check_for_overlapping_inherent_impls(type_def_id);
96 }
97 _ => {}
98 }
99 }
100
101 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
102 }
103
104 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
105 }
106 }