@@ -2,8 +2,9 @@ use rustc_errors::struct_span_err;
2
2
use rustc_hir as hir;
3
3
use rustc_hir:: def_id:: { CrateNum , DefId , LOCAL_CRATE } ;
4
4
use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
5
- use rustc_middle:: ty:: TyCtxt ;
5
+ use rustc_middle:: ty:: { self , TyCtxt } ;
6
6
use rustc_trait_selection:: traits:: { self , SkipLeakCheck } ;
7
+ use smallvec:: SmallVec ;
7
8
8
9
pub fn crate_inherent_impls_overlap_check ( tcx : TyCtxt < ' _ > , crate_num : CrateNum ) {
9
10
assert_eq ! ( crate_num, LOCAL_CRATE ) ;
@@ -18,9 +19,18 @@ struct InherentOverlapChecker<'tcx> {
18
19
impl InherentOverlapChecker < ' tcx > {
19
20
/// Checks whether any associated items in impls 1 and 2 share the same identifier and
20
21
/// 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
+ }
24
34
25
35
for item1 in impl_items1. in_definition_order ( ) {
26
36
let collision = impl_items2. filter_by_name_unhygienic ( item1. ident . name ) . any ( |item2| {
@@ -113,9 +123,20 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
113
123
let ty_def_id = self . tcx . hir ( ) . local_def_id ( item. hir_id ) ;
114
124
let impls = self . tcx . inherent_impls ( ty_def_id) ;
115
125
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) {
119
140
self . check_for_overlapping_inherent_impls ( impl1_def_id, impl2_def_id) ;
120
141
}
121
142
}
0 commit comments