@@ -2,8 +2,9 @@ use rustc_errors::struct_span_err;
22use rustc_hir as hir;
33use rustc_hir:: def_id:: { CrateNum , DefId , LOCAL_CRATE } ;
44use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
5- use rustc_middle:: ty:: TyCtxt ;
5+ use rustc_middle:: ty:: { self , TyCtxt } ;
66use rustc_trait_selection:: traits:: { self , SkipLeakCheck } ;
7+ use smallvec:: SmallVec ;
78
89pub fn crate_inherent_impls_overlap_check ( tcx : TyCtxt < ' _ > , crate_num : CrateNum ) {
910 assert_eq ! ( crate_num, LOCAL_CRATE ) ;
@@ -18,9 +19,18 @@ struct InherentOverlapChecker<'tcx> {
1819impl InherentOverlapChecker < ' tcx > {
1920 /// Checks whether any associated items in impls 1 and 2 share the same identifier and
2021 /// namespace.
21- fn impls_have_common_items ( & self , impl1 : DefId , impl2 : DefId ) -> bool {
22- let impl_items1 = self . tcx . associated_items ( impl1) ;
23- let impl_items2 = self . tcx . associated_items ( impl2) ;
22+ fn impls_have_common_items (
23+ & self ,
24+ impl_items1 : & ty:: AssociatedItems < ' _ > ,
25+ impl_items2 : & ty:: AssociatedItems < ' _ > ,
26+ ) -> bool {
27+ let mut impl_items1 = & impl_items1;
28+ let mut impl_items2 = & impl_items2;
29+
30+ // Performance optimization: iterate over the smaller list
31+ if impl_items1. len ( ) > impl_items2. len ( ) {
32+ std:: mem:: swap ( & mut impl_items1, & mut impl_items2) ;
33+ }
2434
2535 for item1 in impl_items1. in_definition_order ( ) {
2636 let collision = impl_items2. filter_by_name_unhygienic ( item1. ident . name ) . any ( |item2| {
@@ -113,9 +123,20 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
113123 let ty_def_id = self . tcx . hir ( ) . local_def_id ( item. hir_id ) ;
114124 let impls = self . tcx . inherent_impls ( ty_def_id) ;
115125
116- for ( i, & impl1_def_id) in impls. iter ( ) . enumerate ( ) {
117- for & impl2_def_id in & impls[ ( i + 1 ) ..] {
118- if self . impls_have_common_items ( impl1_def_id, impl2_def_id) {
126+ // If there is only one inherent impl block,
127+ // there is nothing to overlap check it with
128+ if impls. len ( ) <= 1 {
129+ return ;
130+ }
131+
132+ let impls_items = impls
133+ . iter ( )
134+ . map ( |impl_def_id| ( impl_def_id, self . tcx . associated_items ( * impl_def_id) ) )
135+ . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
136+
137+ for ( i, & ( & impl1_def_id, impl_items1) ) in impls_items. iter ( ) . enumerate ( ) {
138+ for & ( & impl2_def_id, impl_items2) in & impls_items[ ( i + 1 ) ..] {
139+ if self . impls_have_common_items ( impl_items1, impl_items2) {
119140 self . check_for_overlapping_inherent_impls ( impl1_def_id, impl2_def_id) ;
120141 }
121142 }
0 commit comments