9
9
// except according to those terms.
10
10
11
11
//! Overlap: No two impls for the same trait are implemented for the
12
- //! same type.
12
+ //! same type. Likewise, no two inherent impls for a given type
13
+ //! constructor provide a method with the same name.
13
14
14
15
use middle:: cstore:: { CrateStore , LOCAL_CRATE } ;
15
16
use middle:: def_id:: DefId ;
@@ -115,7 +116,6 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
115
116
}
116
117
}
117
118
118
-
119
119
fn check_if_impls_overlap ( & self ,
120
120
impl1_def_id : DefId ,
121
121
impl2_def_id : DefId )
@@ -128,8 +128,8 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
128
128
impl2_def_id) ;
129
129
130
130
let infcx = infer:: new_infer_ctxt ( self . tcx , & self . tcx . tables , None ) ;
131
- if let Some ( trait_ref ) = traits:: overlapping_impls ( & infcx, impl1_def_id, impl2_def_id) {
132
- self . report_overlap_error ( impl1_def_id, impl2_def_id, trait_ref) ;
131
+ if let Some ( header ) = traits:: overlapping_impls ( & infcx, impl1_def_id, impl2_def_id) {
132
+ self . report_overlap_error ( impl1_def_id, impl2_def_id, header . trait_ref . unwrap ( ) ) ;
133
133
}
134
134
}
135
135
}
@@ -150,13 +150,13 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
150
150
} ) . unwrap_or ( String :: new ( ) )
151
151
} ;
152
152
153
- let mut err = struct_span_err ! ( self . tcx. sess, self . span_of_impl ( impl1) , E0119 ,
153
+ let mut err = struct_span_err ! ( self . tcx. sess, self . span_of_def_id ( impl1) , E0119 ,
154
154
"conflicting implementations of trait `{}`{}:" ,
155
155
trait_ref,
156
156
self_type) ;
157
157
158
158
if impl2. is_local ( ) {
159
- span_note ! ( & mut err, self . span_of_impl ( impl2) ,
159
+ span_note ! ( & mut err, self . span_of_def_id ( impl2) ,
160
160
"conflicting implementation is here:" ) ;
161
161
} else {
162
162
let cname = self . tcx . sess . cstore . crate_name ( impl2. krate ) ;
@@ -165,10 +165,61 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
165
165
err. emit ( ) ;
166
166
}
167
167
168
- fn span_of_impl ( & self , impl_did : DefId ) -> Span {
169
- let node_id = self . tcx . map . as_local_node_id ( impl_did ) . unwrap ( ) ;
168
+ fn span_of_def_id ( & self , did : DefId ) -> Span {
169
+ let node_id = self . tcx . map . as_local_node_id ( did ) . unwrap ( ) ;
170
170
self . tcx . map . span ( node_id)
171
171
}
172
+
173
+ fn check_for_common_items_in_impls ( & self , impl1 : DefId , impl2 : DefId ) {
174
+ #[ derive( Copy , Clone , PartialEq ) ]
175
+ enum Namespace { Type , Value }
176
+
177
+ fn name_and_namespace ( tcx : & TyCtxt , item : & ty:: ImplOrTraitItemId )
178
+ -> ( ast:: Name , Namespace )
179
+ {
180
+ let name = tcx. impl_or_trait_item ( item. def_id ( ) ) . name ( ) ;
181
+ ( name, match * item {
182
+ ty:: TypeTraitItemId ( ..) => Namespace :: Type ,
183
+ ty:: ConstTraitItemId ( ..) => Namespace :: Value ,
184
+ ty:: MethodTraitItemId ( ..) => Namespace :: Value ,
185
+ } )
186
+ }
187
+
188
+ let impl_items = self . tcx . impl_items . borrow ( ) ;
189
+
190
+ for item1 in & impl_items[ & impl1] {
191
+ let ( name, namespace) = name_and_namespace ( & self . tcx , item1) ;
192
+
193
+ for item2 in & impl_items[ & impl2] {
194
+ if ( name, namespace) == name_and_namespace ( & self . tcx , item2) {
195
+ let mut err = super :: report_duplicate_item (
196
+ & self . tcx , self . span_of_def_id ( item1. def_id ( ) ) , name) ;
197
+ span_note ! ( & mut err, self . span_of_def_id( item2. def_id( ) ) ,
198
+ "conflicting definition is here:" ) ;
199
+ err. emit ( ) ;
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ fn check_for_overlapping_inherent_impls ( & self , ty_def_id : DefId ) {
206
+ let _task = self . tcx . dep_graph . in_task ( DepNode :: CoherenceOverlapInherentCheck ( ty_def_id) ) ;
207
+
208
+ let inherent_impls = self . tcx . inherent_impls . borrow ( ) ;
209
+ let impls = match inherent_impls. get ( & ty_def_id) {
210
+ Some ( impls) => impls,
211
+ None => return
212
+ } ;
213
+
214
+ for ( i, & impl1_def_id) in impls. iter ( ) . enumerate ( ) {
215
+ for & impl2_def_id in & impls[ ( i+1 ) ..] {
216
+ let infcx = infer:: new_infer_ctxt ( self . tcx , & self . tcx . tables , None ) ;
217
+ if traits:: overlapping_impls ( & infcx, impl1_def_id, impl2_def_id) . is_some ( ) {
218
+ self . check_for_common_items_in_impls ( impl1_def_id, impl2_def_id)
219
+ }
220
+ }
221
+ }
222
+ }
172
223
}
173
224
174
225
@@ -180,6 +231,11 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
180
231
self . check_for_overlapping_impls_of_trait ( trait_def_id) ;
181
232
}
182
233
234
+ hir:: ItemEnum ( ..) | hir:: ItemStruct ( ..) => {
235
+ let type_def_id = self . tcx . map . local_def_id ( item. id ) ;
236
+ self . check_for_overlapping_inherent_impls ( type_def_id) ;
237
+ }
238
+
183
239
hir:: ItemDefaultImpl ( ..) => {
184
240
// look for another default impl; note that due to the
185
241
// general orphan/coherence rules, it must always be
0 commit comments