]>
Commit | Line | Data |
---|---|---|
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 | 15 | use rustc::traits; |
476ff2be | 16 | use rustc::ty::{self, TyCtxt, TypeFoldable}; |
1a4d82fc | 17 | use syntax::ast; |
9cc50fc6 | 18 | use rustc::dep_graph::DepNode; |
54a0048b | 19 | use rustc::hir; |
476ff2be | 20 | use rustc::hir::itemlikevisit::ItemLikeVisitor; |
1a4d82fc | 21 | |
8bb4bdeb XL |
22 | pub 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 |
30 | pub 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 |
103 | struct OverlapChecker<'cx, 'tcx: 'cx> { |
104 | tcx: TyCtxt<'cx, 'tcx, 'tcx>, | |
105 | } | |
106 | ||
476ff2be | 107 | impl<'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 | } |