@@ -3,8 +3,7 @@ use crate::clean::*;
33use crate :: core:: DocContext ;
44use crate :: fold:: DocFolder ;
55
6- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
7- use rustc_hir:: def_id:: DefId ;
6+ use rustc_data_structures:: fx:: FxHashSet ;
87use rustc_middle:: ty:: DefIdTree ;
98use rustc_span:: symbol:: sym;
109
@@ -53,6 +52,39 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
5352 }
5453 }
5554
55+ let mut cleaner = BadImplStripper { prims, items : crate_items } ;
56+
57+ // scan through included items ahead of time to splice in Deref targets to the "valid" sets
58+ for it in & new_items {
59+ if let ImplItem ( Impl { ref for_, ref trait_, ref items, .. } ) = * it. kind {
60+ if cleaner. keep_impl ( for_) && trait_. def_id ( ) == cx. tcx . lang_items ( ) . deref_trait ( ) {
61+ let target = items
62+ . iter ( )
63+ . find_map ( |item| match * item. kind {
64+ TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
65+ _ => None ,
66+ } )
67+ . expect ( "Deref impl without Target type" ) ;
68+
69+ if let Some ( prim) = target. primitive_type ( ) {
70+ cleaner. prims . insert ( prim) ;
71+ } else if let Some ( did) = target. def_id ( ) {
72+ cleaner. items . insert ( did. into ( ) ) ;
73+ }
74+ }
75+ }
76+ }
77+
78+ new_items. retain ( |it| {
79+ if let ImplItem ( Impl { ref for_, ref trait_, ref blanket_impl, .. } ) = * it. kind {
80+ cleaner. keep_impl ( for_)
81+ || trait_. as_ref ( ) . map_or ( false , |t| cleaner. keep_impl ( t) )
82+ || blanket_impl. is_some ( )
83+ } else {
84+ true
85+ }
86+ } ) ;
87+
5688 // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
5789 // doesn't work with it anyway, so pull them from the HIR map instead
5890 let mut extra_attrs = Vec :: new ( ) ;
@@ -84,73 +116,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
84116 }
85117 }
86118
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. into ( ) ) ;
121- add_deref_target ( map, cleaner, & target_did. into ( ) ) ;
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 ( FakeDefId :: Real ( * type_did) ) {
130- add_deref_target ( & type_did_to_deref_target, & mut cleaner, type_did) ;
131- }
132- }
133-
134119 let items = if let ModuleItem ( Module { ref mut items, .. } ) = * krate. module . kind {
135120 items
136121 } else {
137122 panic ! ( "collect-trait-impls can't run" ) ;
138123 } ;
139124
140125 items. extend ( synth_impls) ;
141- for it in new_items. drain ( ..) {
142- if let ImplItem ( Impl { ref for_, ref trait_, ref blanket_impl, .. } ) = * it. kind {
143- if !( cleaner. keep_impl ( for_)
144- || trait_. as_ref ( ) . map_or ( false , |t| cleaner. keep_impl ( t) )
145- || blanket_impl. is_some ( ) )
146- {
147- continue ;
148- }
149- }
150-
151- items. push ( it) ;
152- }
153-
126+ items. extend ( new_items) ;
154127 krate
155128}
156129
0 commit comments