10
10
11
11
use clean:: * ;
12
12
13
+ use rustc:: util:: nodemap:: FxHashSet ;
14
+ use rustc:: hir:: def_id:: DefId ;
15
+
13
16
use super :: Pass ;
14
17
use core:: DocContext ;
15
18
use fold:: DocFolder ;
@@ -22,22 +25,20 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate {
22
25
let mut synth = SyntheticImplCollector :: new ( cx) ;
23
26
let mut krate = synth. fold_crate ( krate) ;
24
27
25
- if let Some ( ref mut it) = krate. module {
26
- if let ModuleItem ( Module { ref mut items, .. } ) = it. inner {
27
- items. extend ( synth. impls ) ;
28
+ let prims: FxHashSet < PrimitiveType > =
29
+ krate. primitives . iter ( ) . map ( |p| p. 1 ) . collect ( ) ;
30
+
31
+ let crate_items = {
32
+ let mut coll = ItemCollector :: new ( ) ;
33
+ krate = coll. fold_crate ( krate) ;
34
+ coll. items
35
+ } ;
36
+
37
+ let mut new_items = Vec :: new ( ) ;
28
38
29
39
for & cnum in cx. tcx . crates ( ) . iter ( ) {
30
40
for & did in cx. tcx . all_trait_implementations ( cnum) . iter ( ) {
31
- inline:: build_impl ( cx, did, items) ;
32
- }
33
- }
34
-
35
- // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
36
- // doesn't work with it anyway, so pull them from the HIR map instead
37
- for & trait_did in cx. all_traits . iter ( ) {
38
- for & impl_node in cx. tcx . hir . trait_impls ( trait_did) {
39
- let impl_did = cx. tcx . hir . local_def_id ( impl_node) ;
40
- inline:: build_impl ( cx, impl_did, items) ;
41
+ inline:: build_impl ( cx, did, & mut new_items) ;
41
42
}
42
43
}
43
44
@@ -73,7 +74,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate {
73
74
74
75
for def_id in primitive_impls. iter ( ) . filter_map ( |& def_id| def_id) {
75
76
if !def_id. is_local ( ) {
76
- inline:: build_impl ( cx, def_id, items ) ;
77
+ inline:: build_impl ( cx, def_id, & mut new_items ) ;
77
78
78
79
let auto_impls = get_auto_traits_with_def_id ( cx, def_id) ;
79
80
let blanket_impls = get_blanket_impls_with_def_id ( cx, def_id) ;
@@ -84,9 +85,58 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate {
84
85
. filter ( |i| renderinfo. inlined . insert ( i. def_id ) )
85
86
. collect ( ) ;
86
87
87
- items . extend ( new_impls) ;
88
+ new_items . extend ( new_impls) ;
88
89
}
89
90
}
91
+
92
+ let mut cleaner = BadImplStripper {
93
+ prims,
94
+ items : crate_items,
95
+ } ;
96
+
97
+ // scan through included items ahead of time to splice in Deref targets to the "valid" sets
98
+ for it in & new_items {
99
+ if let ImplItem ( Impl { ref for_, ref trait_, ref items, .. } ) = it. inner {
100
+ if cleaner. keep_item ( for_) && trait_. def_id ( ) == cx. tcx . lang_items ( ) . deref_trait ( ) {
101
+ let target = items. iter ( ) . filter_map ( |item| {
102
+ match item. inner {
103
+ TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
104
+ _ => None ,
105
+ }
106
+ } ) . next ( ) . expect ( "Deref impl without Target type" ) ;
107
+
108
+ if let Some ( prim) = target. primitive_type ( ) {
109
+ cleaner. prims . insert ( prim) ;
110
+ } else if let Some ( did) = target. def_id ( ) {
111
+ cleaner. items . insert ( did) ;
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ new_items. retain ( |it| {
118
+ if let ImplItem ( Impl { ref for_, ref trait_, ref blanket_impl, .. } ) = it. inner {
119
+ cleaner. keep_item ( for_) ||
120
+ trait_. as_ref ( ) . map_or ( false , |t| cleaner. keep_item ( t) ) ||
121
+ blanket_impl. is_some ( )
122
+ } else {
123
+ true
124
+ }
125
+ } ) ;
126
+
127
+ // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
128
+ // doesn't work with it anyway, so pull them from the HIR map instead
129
+ for & trait_did in cx. all_traits . iter ( ) {
130
+ for & impl_node in cx. tcx . hir . trait_impls ( trait_did) {
131
+ let impl_did = cx. tcx . hir . local_def_id ( impl_node) ;
132
+ inline:: build_impl ( cx, impl_did, & mut new_items) ;
133
+ }
134
+ }
135
+
136
+ if let Some ( ref mut it) = krate. module {
137
+ if let ModuleItem ( Module { ref mut items, .. } ) = it. inner {
138
+ items. extend ( synth. impls ) ;
139
+ items. extend ( new_items) ;
90
140
} else {
91
141
panic ! ( "collect-trait-impls can't run" ) ;
92
142
}
@@ -128,3 +178,42 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for SyntheticImplCollector<'a, 'tcx, 'rc
128
178
self . fold_item_recur ( i)
129
179
}
130
180
}
181
+
182
+ #[ derive( Default ) ]
183
+ struct ItemCollector {
184
+ items : FxHashSet < DefId > ,
185
+ }
186
+
187
+ impl ItemCollector {
188
+ fn new ( ) -> Self {
189
+ Self :: default ( )
190
+ }
191
+ }
192
+
193
+ impl DocFolder for ItemCollector {
194
+ fn fold_item ( & mut self , i : Item ) -> Option < Item > {
195
+ self . items . insert ( i. def_id ) ;
196
+
197
+ self . fold_item_recur ( i)
198
+ }
199
+ }
200
+
201
+ struct BadImplStripper {
202
+ prims : FxHashSet < PrimitiveType > ,
203
+ items : FxHashSet < DefId > ,
204
+ }
205
+
206
+ impl BadImplStripper {
207
+ fn keep_item ( & self , ty : & Type ) -> bool {
208
+ if let Generic ( _) = ty {
209
+ // keep impls made on generics
210
+ true
211
+ } else if let Some ( prim) = ty. primitive_type ( ) {
212
+ self . prims . contains ( & prim)
213
+ } else if let Some ( did) = ty. def_id ( ) {
214
+ self . items . contains ( & did)
215
+ } else {
216
+ false
217
+ }
218
+ }
219
+ }
0 commit comments