@@ -3,8 +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 } ;
7
- use rustc_hir:: def_id:: DefId ;
6
+ use rustc_data_structures:: fx:: FxHashSet ;
8
7
use rustc_middle:: ty:: DefIdTree ;
9
8
use rustc_span:: symbol:: sym;
10
9
@@ -53,6 +52,39 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
53
52
}
54
53
}
55
54
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
+
56
88
// `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
57
89
// doesn't work with it anyway, so pull them from the HIR map instead
58
90
let mut extra_attrs = Vec :: new ( ) ;
@@ -84,73 +116,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
84
116
}
85
117
}
86
118
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
-
134
119
let items = if let ModuleItem ( Module { ref mut items, .. } ) = * krate. module . kind {
135
120
items
136
121
} else {
137
122
panic ! ( "collect-trait-impls can't run" ) ;
138
123
} ;
139
124
140
125
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) ;
154
127
krate
155
128
}
156
129
0 commit comments