@@ -3,7 +3,7 @@ use crate::clean::*;
3
3
use crate :: core:: DocContext ;
4
4
use crate :: fold:: DocFolder ;
5
5
6
- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
6
+ use rustc_data_structures:: fx:: FxHashSet ;
7
7
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
8
8
use rustc_middle:: ty:: DefIdTree ;
9
9
use rustc_span:: symbol:: sym;
@@ -53,6 +53,39 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
53
53
}
54
54
}
55
55
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
+
56
89
// `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
57
90
// doesn't work with it anyway, so pull them from the HIR map instead
58
91
let mut extra_attrs = Vec :: new ( ) ;
@@ -84,73 +117,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
84
117
}
85
118
}
86
119
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
-
134
120
let items = if let ModuleItem ( Module { ref mut items, .. } ) = * krate. module . kind {
135
121
items
136
122
} else {
137
123
panic ! ( "collect-trait-impls can't run" ) ;
138
124
} ;
139
125
140
126
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
-
127
+ items. extend ( new_items) ;
154
128
krate
155
129
}
156
130
@@ -204,13 +178,9 @@ impl BadImplStripper {
204
178
} else if let Some ( prim) = ty. primitive_type ( ) {
205
179
self . prims . contains ( & prim)
206
180
} else if let Some ( did) = ty. def_id ( ) {
207
- self . keep_impl_with_def_id ( & did)
181
+ self . items . contains ( & did)
208
182
} else {
209
183
false
210
184
}
211
185
}
212
-
213
- fn keep_impl_with_def_id ( & self , did : & DefId ) -> bool {
214
- self . items . contains ( did)
215
- }
216
186
}
0 commit comments