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.
16 use rustc
::ty
::{self, TyCtxt, TypeFoldable}
;
18 use rustc
::dep_graph
::DepNode
;
20 use rustc
::hir
::itemlikevisit
::ItemLikeVisitor
;
22 pub fn check_default_impls
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) {
23 let mut overlap
= OverlapChecker { tcx }
;
25 // this secondary walk specifically checks for some other cases,
26 // like defaulted traits, for which additional overlap rules exist
27 tcx
.hir
.krate().visit_all_item_likes(&mut overlap
);
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
;
35 if trait_ref
.references_error() {
36 debug
!("coherence: skipping impl {:?} with error {:?}",
37 impl_def_id
, trait_ref
);
42 tcx
.dep_graph
.in_task(DepNode
::CoherenceOverlapCheck(trait_def_id
));
44 let def
= tcx
.lookup_trait_def(trait_def_id
);
46 // attempt to insert into the specialization graph
47 let insert_result
= def
.add_impl_for_specialization(tcx
, impl_def_id
);
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(),
54 "conflicting implementations of trait `{}`{}:",
56 overlap
.self_desc
.clone().map_or(String
::new(),
58 format
!(" for type `{}`", ty
)
61 match tcx
.span_of_impl(overlap
.with_impl
) {
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{}",
67 .map_or(String
::new(),
68 |ty
| format
!(" for `{}`", ty
))));
71 err
.note(&format
!("conflicting implementation in crate `{}`", cname
));
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.
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`.
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
) {
92 tcx
.span_of_impl(impl_def_id
).unwrap(),
94 "the object type `{}` automatically \
95 implements the trait `{}`",
97 tcx
.item_path_str(trait_def_id
));
103 struct OverlapChecker
<'cx
, 'tcx
: 'cx
> {
104 tcx
: TyCtxt
<'cx
, 'tcx
, 'tcx
>,
107 impl<'cx
, 'tcx
, 'v
> ItemLikeVisitor
<'v
> for OverlapChecker
<'cx
, 'tcx
> {
108 fn visit_item(&mut self, item
: &'v hir
::Item
) {
110 hir
::ItemDefaultImpl(..) => {
111 // look for another default impl; note that due to the
112 // general orphan/coherence rules, it must always be
114 let impl_def_id
= self.tcx
.hir
.local_def_id(item
.id
);
115 let trait_ref
= self.tcx
.impl_trait_ref(impl_def_id
).unwrap();
117 let prev_id
= self.tcx
.hir
.trait_default_impl(trait_ref
.def_id
).unwrap();
118 if prev_id
!= item
.id
{
119 let mut err
= struct_span_err
!(self.tcx
.sess
,
120 self.tcx
.span_of_impl(impl_def_id
).unwrap(),
122 "redundant default implementations of trait \
125 err
.span_note(self.tcx
126 .span_of_impl(self.tcx
.hir
.local_def_id(prev_id
))
128 "redundant implementation is here:");
132 hir
::ItemImpl(.., Some(_
), _
, _
) => {
138 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
) {
141 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
) {