@@ -3,7 +3,7 @@ use crate::clean::*;
33use crate :: core:: DocContext ;
44use crate :: fold:: DocFolder ;
55
6- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
6+ use rustc_data_structures:: fx:: { FxHashSet } ;
77use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
88use rustc_middle:: ty:: DefIdTree ;
99use rustc_span:: symbol:: sym;
@@ -53,6 +53,39 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
5353 }
5454 }
5555
56+ let mut cleaner = BadImplStripper { prims, items : crate_items } ;
57+
58+ // scan through included items ahead of time to splice in Deref targets to the "valid" sets
59+ for it in & new_items {
60+ if let ImplItem ( Impl { ref for_, ref trait_, ref items, .. } ) = * it. kind {
61+ if cleaner. keep_impl ( for_) && trait_. def_id ( ) == cx. tcx . lang_items ( ) . deref_trait ( ) {
62+ let target = items
63+ . iter ( )
64+ . find_map ( |item| match * item. kind {
65+ TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
66+ _ => None ,
67+ } )
68+ . expect ( "Deref impl without Target type" ) ;
69+
70+ if let Some ( prim) = target. primitive_type ( ) {
71+ cleaner. prims . insert ( prim) ;
72+ } else if let Some ( did) = target. def_id ( ) {
73+ cleaner. items . insert ( did) ;
74+ }
75+ }
76+ }
77+ }
78+
79+ new_items. retain ( |it| {
80+ if let ImplItem ( Impl { ref for_, ref trait_, ref blanket_impl, .. } ) = * it. kind {
81+ cleaner. keep_impl ( for_)
82+ || trait_. as_ref ( ) . map_or ( false , |t| cleaner. keep_impl ( t) )
83+ || blanket_impl. is_some ( )
84+ } else {
85+ true
86+ }
87+ } ) ;
88+
5689 // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
5790 // doesn't work with it anyway, so pull them from the HIR map instead
5891 let mut extra_attrs = Vec :: new ( ) ;
@@ -84,53 +117,6 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
84117 }
85118 }
86119
87- let mut cleaner = BadImplStripper { prims, items : crate_items } ;
88-
89- let mut type_did_to_deref_target: FxHashMap < DefId , & Type > = FxHashMap :: default ( ) ;
90- // Gather all type to `Deref` target edges.
91- for it in & new_items {
92- if let ImplItem ( Impl { ref for_, ref trait_, ref items, .. } ) = * it. kind {
93- if trait_. def_id ( ) == cx. tcx . lang_items ( ) . deref_trait ( ) {
94- let target = items. iter ( ) . find_map ( |item| match * item. kind {
95- TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
96- _ => None ,
97- } ) ;
98- if let ( Some ( for_did) , Some ( target) ) = ( for_. def_id ( ) , target) {
99- type_did_to_deref_target. insert ( for_did, target) ;
100- }
101- }
102- }
103- }
104- // Follow all `Deref` targets of included items and recursively add them as valid
105- fn add_deref_target (
106- map : & FxHashMap < DefId , & Type > ,
107- cleaner : & mut BadImplStripper ,
108- type_did : & DefId ,
109- ) {
110- if let Some ( target) = map. get ( type_did) {
111- debug ! ( "add_deref_target: type {:?}, target {:?}" , type_did, target) ;
112- if let Some ( target_prim) = target. primitive_type ( ) {
113- cleaner. prims . insert ( target_prim) ;
114- } else if let Some ( target_did) = target. def_id ( ) {
115- // `impl Deref<Target = S> for S`
116- if target_did == * type_did {
117- // Avoid infinite cycles
118- return ;
119- }
120- cleaner. items . insert ( target_did) ;
121- add_deref_target ( map, cleaner, & target_did) ;
122- }
123- }
124- }
125- for type_did in type_did_to_deref_target. keys ( ) {
126- // Since only the `DefId` portion of the `Type` instances is known to be same for both the
127- // `Deref` target type and the impl for type positions, this map of types is keyed by
128- // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
129- if cleaner. keep_impl_with_def_id ( type_did) {
130- add_deref_target ( & type_did_to_deref_target, & mut cleaner, type_did) ;
131- }
132- }
133-
134120 let items = if let Some ( ref mut it) = krate. module {
135121 if let ModuleItem ( Module { ref mut items, .. } ) = * it. kind {
136122 items
@@ -142,18 +128,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
142128 } ;
143129
144130 items. extend ( synth_impls) ;
145- for it in new_items. drain ( ..) {
146- if let ImplItem ( Impl { ref for_, ref trait_, ref blanket_impl, .. } ) = * it. kind {
147- if !( cleaner. keep_impl ( for_)
148- || trait_. as_ref ( ) . map_or ( false , |t| cleaner. keep_impl ( t) )
149- || blanket_impl. is_some ( ) )
150- {
151- continue ;
152- }
153- }
154-
155- items. push ( it) ;
156- }
131+ items. extend ( new_items) ;
157132
158133 krate
159134}
@@ -208,13 +183,9 @@ impl BadImplStripper {
208183 } else if let Some ( prim) = ty. primitive_type ( ) {
209184 self . prims . contains ( & prim)
210185 } else if let Some ( did) = ty. def_id ( ) {
211- self . keep_impl_with_def_id ( & did)
186+ self . items . contains ( & did)
212187 } else {
213188 false
214189 }
215190 }
216-
217- fn keep_impl_with_def_id ( & self , did : & DefId ) -> bool {
218- self . items . contains ( did)
219- }
220191}
0 commit comments