]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/coherence/overlap.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_typeck / coherence / overlap.rs
CommitLineData
1a4d82fc
JJ
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
54a0048b
SL
12//! same type. Likewise, no two inherent impls for a given type
13//! constructor provide a method with the same name.
14
8bb4bdeb 15use rustc::traits;
476ff2be 16use rustc::ty::{self, TyCtxt, TypeFoldable};
1a4d82fc 17use syntax::ast;
9cc50fc6 18use rustc::dep_graph::DepNode;
54a0048b 19use rustc::hir;
476ff2be 20use rustc::hir::itemlikevisit::ItemLikeVisitor;
1a4d82fc 21
8bb4bdeb
XL
22pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
23 let mut overlap = OverlapChecker { tcx };
c34b1796 24
9346a6ac
AL
25 // this secondary walk specifically checks for some other cases,
26 // like defaulted traits, for which additional overlap rules exist
476ff2be 27 tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial, &mut overlap);
1a4d82fc
JJ
28}
29
8bb4bdeb
XL
30pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
31 let impl_def_id = tcx.hir.local_def_id(node_id);
32 let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
33 let trait_def_id = trait_ref.def_id;
1a4d82fc 34
8bb4bdeb
XL
35 if trait_ref.references_error() {
36 debug!("coherence: skipping impl {:?} with error {:?}",
37 impl_def_id, trait_ref);
38 return
39 }
9cc50fc6 40
8bb4bdeb
XL
41 let _task =
42 tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id));
43
44 let def = tcx.lookup_trait_def(trait_def_id);
45
46 // attempt to insert into the specialization graph
47 let insert_result = def.add_impl_for_specialization(tcx, impl_def_id);
48
49 // insertion failed due to overlap
50 if let Err(overlap) = insert_result {
51 let mut err = struct_span_err!(tcx.sess,
52 tcx.span_of_impl(impl_def_id).unwrap(),
53 E0119,
54 "conflicting implementations of trait `{}`{}:",
55 overlap.trait_desc,
56 overlap.self_desc.clone().map_or(String::new(),
57 |ty| {
58 format!(" for type `{}`", ty)
59 }));
60
61 match tcx.span_of_impl(overlap.with_impl) {
62 Ok(span) => {
63 err.span_label(span, &format!("first implementation here"));
64 err.span_label(tcx.span_of_impl(impl_def_id).unwrap(),
65 &format!("conflicting implementation{}",
66 overlap.self_desc
67 .map_or(String::new(),
68 |ty| format!(" for `{}`", ty))));
69 }
70 Err(cname) => {
71 err.note(&format!("conflicting implementation in crate `{}`", cname));
d9579d0f 72 }
1a4d82fc 73 }
8bb4bdeb
XL
74
75 err.emit();
1a4d82fc
JJ
76 }
77
8bb4bdeb
XL
78 // check for overlap with the automatic `impl Trait for Trait`
79 if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
80 // This is something like impl Trait1 for Trait2. Illegal
81 // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
82
83 if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
84 // This is an error, but it will be reported by wfcheck. Ignore it here.
85 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
86 } else {
87 let mut supertrait_def_ids =
88 traits::supertrait_def_ids(tcx,
89 data.principal().unwrap().def_id());
90 if supertrait_def_ids.any(|d| d == trait_def_id) {
91 span_err!(tcx.sess,
92 tcx.span_of_impl(impl_def_id).unwrap(),
93 E0371,
94 "the object type `{}` automatically \
95 implements the trait `{}`",
96 trait_ref.self_ty(),
97 tcx.item_path_str(trait_def_id));
54a0048b 98 }
1a4d82fc 99 }
1a4d82fc
JJ
100 }
101}
c34b1796 102
8bb4bdeb
XL
103struct OverlapChecker<'cx, 'tcx: 'cx> {
104 tcx: TyCtxt<'cx, 'tcx, 'tcx>,
105}
106
476ff2be 107impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
e9174d1e 108 fn visit_item(&mut self, item: &'v hir::Item) {
c34b1796 109 match item.node {
9cc50fc6 110 hir::ItemDefaultImpl(..) => {
c34b1796
AL
111 // look for another default impl; note that due to the
112 // general orphan/coherence rules, it must always be
113 // in this crate.
32a655c1 114 let impl_def_id = self.tcx.hir.local_def_id(item.id);
c1a9b12d 115 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
9cc50fc6 116
8bb4bdeb
XL
117 let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap();
118 if prev_id != item.id {
c30ab7b3
SL
119 let mut err = struct_span_err!(self.tcx.sess,
120 self.tcx.span_of_impl(impl_def_id).unwrap(),
121 E0521,
122 "redundant default implementations of trait \
123 `{}`:",
124 trait_ref);
125 err.span_note(self.tcx
32a655c1 126 .span_of_impl(self.tcx.hir.local_def_id(prev_id))
54a0048b
SL
127 .unwrap(),
128 "redundant implementation is here:");
129 err.emit();
c34b1796
AL
130 }
131 }
9e0c209e 132 hir::ItemImpl(.., Some(_), _, _) => {
9346a6ac 133 }
54a0048b 134 _ => {}
c34b1796
AL
135 }
136 }
476ff2be 137
32a655c1
SL
138 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
139 }
140
476ff2be
SL
141 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
142 }
c34b1796 143}