@@ -35,6 +35,60 @@ pub struct TraitDef {
3535 pub def_path_hash : u64 ,
3636}
3737
38+ // We don't store the list of impls in a flat list because each cached list of
39+ // `relevant_impls_for` we would then duplicate all blanket impls. By keeping
40+ // blanket and non-blanket impls separate, we can share the list of blanket
41+ // impls.
42+ #[ derive( Clone ) ]
43+ pub struct TraitImpls {
44+ blanket_impls : Rc < Vec < DefId > > ,
45+ non_blanket_impls : Rc < Vec < DefId > > ,
46+ }
47+
48+ impl TraitImpls {
49+ pub fn iter ( & self ) -> TraitImplsIter {
50+ TraitImplsIter {
51+ blanket_impls : self . blanket_impls . clone ( ) ,
52+ non_blanket_impls : self . non_blanket_impls . clone ( ) ,
53+ index : 0
54+ }
55+ }
56+ }
57+
58+ #[ derive( Clone ) ]
59+ pub struct TraitImplsIter {
60+ blanket_impls : Rc < Vec < DefId > > ,
61+ non_blanket_impls : Rc < Vec < DefId > > ,
62+ index : usize ,
63+ }
64+
65+ impl Iterator for TraitImplsIter {
66+ type Item = DefId ;
67+
68+ fn next ( & mut self ) -> Option < DefId > {
69+ if self . index < self . blanket_impls . len ( ) {
70+ let bi_index = self . index ;
71+ self . index += 1 ;
72+ Some ( self . blanket_impls [ bi_index] )
73+ } else {
74+ let nbi_index = self . index - self . blanket_impls . len ( ) ;
75+ if nbi_index < self . non_blanket_impls . len ( ) {
76+ self . index += 1 ;
77+ Some ( self . non_blanket_impls [ nbi_index] )
78+ } else {
79+ None
80+ }
81+ }
82+ }
83+
84+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
85+ let items_left = ( self . blanket_impls . len ( ) + self . non_blanket_impls . len ( ) ) - self . index ;
86+ ( items_left, Some ( items_left) )
87+ }
88+ }
89+
90+ impl ExactSizeIterator for TraitImplsIter { }
91+
3892impl < ' a , ' gcx , ' tcx > TraitDef {
3993 pub fn new ( def_id : DefId ,
4094 unsafety : hir:: Unsafety ,
@@ -58,7 +112,7 @@ impl<'a, 'gcx, 'tcx> TraitDef {
58112 }
59113
60114 pub fn for_each_impl < F : FnMut ( DefId ) > ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > , mut f : F ) {
61- for & impl_def_id in tcx. trait_impls_of ( self . def_id ) . iter ( ) {
115+ for impl_def_id in tcx. trait_impls_of ( self . def_id ) . iter ( ) {
62116 f ( impl_def_id) ;
63117 }
64118 }
@@ -89,7 +143,7 @@ impl<'a, 'gcx, 'tcx> TraitDef {
89143 tcx. trait_impls_of ( self . def_id )
90144 } ;
91145
92- for & impl_def_id in relevant_impls. iter ( ) {
146+ for impl_def_id in relevant_impls. iter ( ) {
93147 f ( impl_def_id) ;
94148 }
95149 }
@@ -98,55 +152,70 @@ impl<'a, 'gcx, 'tcx> TraitDef {
98152// Query provider for `trait_impls_of`.
99153pub ( super ) fn trait_impls_of_provider < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
100154 trait_id : DefId )
101- -> Rc < Vec < DefId > > {
102- let mut impls = if trait_id. is_local ( ) {
155+ -> TraitImpls {
156+ let remote_impls = if trait_id. is_local ( ) {
103157 // Traits defined in the current crate can't have impls in upstream
104158 // crates, so we don't bother querying the cstore.
105159 Vec :: new ( )
106160 } else {
107161 tcx. sess . cstore . implementations_of_trait ( Some ( trait_id) )
108162 } ;
109163
110- impls. extend ( tcx. hir
111- . trait_impls ( trait_id)
112- . iter ( )
113- . map ( |& node_id| tcx. hir . local_def_id ( node_id) )
114- . filter ( |& impl_def_id| {
115- let trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
116- !trait_ref. references_error ( )
117- } ) ) ;
118- Rc :: new ( impls)
164+ let mut blanket_impls = Vec :: new ( ) ;
165+ let mut non_blanket_impls = Vec :: new ( ) ;
166+
167+ let local_impls = tcx. hir
168+ . trait_impls ( trait_id)
169+ . into_iter ( )
170+ . map ( |& node_id| tcx. hir . local_def_id ( node_id) ) ;
171+
172+ for impl_def_id in local_impls. chain ( remote_impls. into_iter ( ) ) {
173+ let impl_trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
174+ if impl_def_id. is_local ( ) && impl_trait_ref. references_error ( ) {
175+ continue
176+ }
177+
178+ if fast_reject:: simplify_type ( tcx, impl_trait_ref. self_ty ( ) , false ) . is_some ( ) {
179+ non_blanket_impls. push ( impl_def_id) ;
180+ } else {
181+ blanket_impls. push ( impl_def_id) ;
182+ }
183+ }
184+
185+ TraitImpls {
186+ blanket_impls : Rc :: new ( blanket_impls) ,
187+ non_blanket_impls : Rc :: new ( non_blanket_impls) ,
188+ }
119189}
120190
121191// Query provider for `relevant_trait_impls_for`.
122192pub ( super ) fn relevant_trait_impls_provider < ' a , ' tcx > (
123193 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
124194 ( trait_id, self_ty) : ( DefId , fast_reject:: SimplifiedType ) )
125- -> Rc < Vec < DefId > >
195+ -> TraitImpls
126196{
127197 let all_trait_impls = tcx. trait_impls_of ( trait_id) ;
128198
129199 let relevant: Vec < DefId > = all_trait_impls
200+ . non_blanket_impls
130201 . iter ( )
131- . map ( | & impl_def_id| impl_def_id )
202+ . cloned ( )
132203 . filter ( |& impl_def_id| {
133204 let impl_trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
134205 let impl_simple_self_ty = fast_reject:: simplify_type ( tcx,
135206 impl_trait_ref. self_ty ( ) ,
136- false ) ;
137- if let Some ( impl_simple_self_ty) = impl_simple_self_ty {
138- impl_simple_self_ty == self_ty
139- } else {
140- // blanket impl (?)
141- true
142- }
207+ false ) . unwrap ( ) ;
208+ impl_simple_self_ty == self_ty
143209 } )
144210 . collect ( ) ;
145211
146- if all_trait_impls. len ( ) == relevant. len ( ) {
212+ if all_trait_impls. non_blanket_impls . len ( ) == relevant. len ( ) {
147213 // If we didn't filter anything out, re-use the existing vec.
148214 all_trait_impls
149215 } else {
150- Rc :: new ( relevant)
216+ TraitImpls {
217+ blanket_impls : all_trait_impls. blanket_impls . clone ( ) ,
218+ non_blanket_impls : Rc :: new ( relevant) ,
219+ }
151220 }
152221}
0 commit comments