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,71 +25,118 @@ 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 ( ) ;
28
30
29
- for & cnum in cx . tcx . crates ( ) . iter ( ) {
30
- for & did in cx . tcx . all_trait_implementations ( cnum ) . iter ( ) {
31
- inline :: build_impl ( cx , did , items ) ;
32
- }
33
- }
31
+ let crate_items = {
32
+ let mut coll = ItemCollector :: new ( ) ;
33
+ krate = coll . fold_crate ( krate ) ;
34
+ coll . items
35
+ } ;
34
36
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
- }
42
- }
37
+ let mut new_items = Vec :: new ( ) ;
38
+
39
+ for & cnum in cx. tcx . crates ( ) . iter ( ) {
40
+ for & did in cx. tcx . all_trait_implementations ( cnum) . iter ( ) {
41
+ inline:: build_impl ( cx, did, & mut new_items) ;
42
+ }
43
+ }
43
44
44
- // Also try to inline primitive impls from other crates.
45
- let lang_items = cx. tcx . lang_items ( ) ;
46
- let primitive_impls = [
47
- lang_items. isize_impl ( ) ,
48
- lang_items. i8_impl ( ) ,
49
- lang_items. i16_impl ( ) ,
50
- lang_items. i32_impl ( ) ,
51
- lang_items. i64_impl ( ) ,
52
- lang_items. i128_impl ( ) ,
53
- lang_items. usize_impl ( ) ,
54
- lang_items. u8_impl ( ) ,
55
- lang_items. u16_impl ( ) ,
56
- lang_items. u32_impl ( ) ,
57
- lang_items. u64_impl ( ) ,
58
- lang_items. u128_impl ( ) ,
59
- lang_items. f32_impl ( ) ,
60
- lang_items. f64_impl ( ) ,
61
- lang_items. f32_runtime_impl ( ) ,
62
- lang_items. f64_runtime_impl ( ) ,
63
- lang_items. char_impl ( ) ,
64
- lang_items. str_impl ( ) ,
65
- lang_items. slice_impl ( ) ,
66
- lang_items. slice_u8_impl ( ) ,
67
- lang_items. str_alloc_impl ( ) ,
68
- lang_items. slice_alloc_impl ( ) ,
69
- lang_items. slice_u8_alloc_impl ( ) ,
70
- lang_items. const_ptr_impl ( ) ,
71
- lang_items. mut_ptr_impl ( ) ,
72
- ] ;
73
-
74
- for def_id in primitive_impls. iter ( ) . filter_map ( |& def_id| def_id) {
75
- if !def_id. is_local ( ) {
76
- inline:: build_impl ( cx, def_id, items) ;
77
-
78
- let auto_impls = get_auto_traits_with_def_id ( cx, def_id) ;
79
- let blanket_impls = get_blanket_impls_with_def_id ( cx, def_id) ;
80
- let mut renderinfo = cx. renderinfo . borrow_mut ( ) ;
81
-
82
- let new_impls: Vec < Item > = auto_impls. into_iter ( )
83
- . chain ( blanket_impls. into_iter ( ) )
84
- . filter ( |i| renderinfo. inlined . insert ( i. def_id ) )
85
- . collect ( ) ;
86
-
87
- items. extend ( new_impls) ;
45
+ // Also try to inline primitive impls from other crates.
46
+ let lang_items = cx. tcx . lang_items ( ) ;
47
+ let primitive_impls = [
48
+ lang_items. isize_impl ( ) ,
49
+ lang_items. i8_impl ( ) ,
50
+ lang_items. i16_impl ( ) ,
51
+ lang_items. i32_impl ( ) ,
52
+ lang_items. i64_impl ( ) ,
53
+ lang_items. i128_impl ( ) ,
54
+ lang_items. usize_impl ( ) ,
55
+ lang_items. u8_impl ( ) ,
56
+ lang_items. u16_impl ( ) ,
57
+ lang_items. u32_impl ( ) ,
58
+ lang_items. u64_impl ( ) ,
59
+ lang_items. u128_impl ( ) ,
60
+ lang_items. f32_impl ( ) ,
61
+ lang_items. f64_impl ( ) ,
62
+ lang_items. f32_runtime_impl ( ) ,
63
+ lang_items. f64_runtime_impl ( ) ,
64
+ lang_items. char_impl ( ) ,
65
+ lang_items. str_impl ( ) ,
66
+ lang_items. slice_impl ( ) ,
67
+ lang_items. slice_u8_impl ( ) ,
68
+ lang_items. str_alloc_impl ( ) ,
69
+ lang_items. slice_alloc_impl ( ) ,
70
+ lang_items. slice_u8_alloc_impl ( ) ,
71
+ lang_items. const_ptr_impl ( ) ,
72
+ lang_items. mut_ptr_impl ( ) ,
73
+ ] ;
74
+
75
+ for def_id in primitive_impls. iter ( ) . filter_map ( |& def_id| def_id) {
76
+ if !def_id. is_local ( ) {
77
+ inline:: build_impl ( cx, def_id, & mut new_items) ;
78
+
79
+ let auto_impls = get_auto_traits_with_def_id ( cx, def_id) ;
80
+ let blanket_impls = get_blanket_impls_with_def_id ( cx, def_id) ;
81
+ let mut renderinfo = cx. renderinfo . borrow_mut ( ) ;
82
+
83
+ let new_impls: Vec < Item > = auto_impls. into_iter ( )
84
+ . chain ( blanket_impls. into_iter ( ) )
85
+ . filter ( |i| renderinfo. inlined . insert ( i. def_id ) )
86
+ . collect ( ) ;
87
+
88
+ new_items. extend ( new_impls) ;
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) ;
88
112
}
89
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