@@ -33,21 +33,50 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
33
33
coll. items
34
34
} ;
35
35
36
- let mut new_items = Vec :: new ( ) ;
36
+ let mut new_items_external = Vec :: new ( ) ;
37
+ let mut new_items_local = Vec :: new ( ) ;
37
38
38
39
// External trait impls.
39
40
cx. with_all_trait_impls ( |cx, all_trait_impls| {
40
41
let _prof_timer = cx. tcx . sess . prof . generic_activity ( "build_extern_trait_impls" ) ;
41
42
for & impl_def_id in all_trait_impls. iter ( ) . skip_while ( |def_id| def_id. is_local ( ) ) {
42
- inline:: build_impl ( cx, None , impl_def_id, None , & mut new_items) ;
43
+ inline:: build_impl ( cx, None , impl_def_id, None , & mut new_items_external) ;
44
+ }
45
+ } ) ;
46
+
47
+ // Local trait impls.
48
+ cx. with_all_trait_impls ( |cx, all_trait_impls| {
49
+ let _prof_timer = cx. tcx . sess . prof . generic_activity ( "build_local_trait_impls" ) ;
50
+ let mut attr_buf = Vec :: new ( ) ;
51
+ for & impl_def_id in all_trait_impls. iter ( ) . take_while ( |def_id| def_id. is_local ( ) ) {
52
+ let mut parent = cx. tcx . parent ( impl_def_id) ;
53
+ while let Some ( did) = parent {
54
+ attr_buf. extend (
55
+ cx. tcx
56
+ . get_attrs ( did)
57
+ . iter ( )
58
+ . filter ( |attr| attr. has_name ( sym:: doc) )
59
+ . filter ( |attr| {
60
+ if let Some ( [ attr] ) = attr. meta_item_list ( ) . as_deref ( ) {
61
+ attr. has_name ( sym:: cfg)
62
+ } else {
63
+ false
64
+ }
65
+ } )
66
+ . cloned ( ) ,
67
+ ) ;
68
+ parent = cx. tcx . parent ( did) ;
69
+ }
70
+ inline:: build_impl ( cx, None , impl_def_id, Some ( & attr_buf) , & mut new_items_local) ;
71
+ attr_buf. clear ( ) ;
43
72
}
44
73
} ) ;
45
74
46
75
cx. tcx . sess . prof . generic_activity ( "build_primitive_trait_impls" ) . run ( || {
47
76
for def_id in PrimitiveType :: all_impls ( cx. tcx ) {
48
77
// Try to inline primitive impls from other crates.
49
78
if !def_id. is_local ( ) {
50
- inline:: build_impl ( cx, None , def_id, None , & mut new_items ) ;
79
+ inline:: build_impl ( cx, None , def_id, None , & mut new_items_external ) ;
51
80
}
52
81
}
53
82
for ( prim, did) in PrimitiveType :: primitive_locations ( cx. tcx ) {
@@ -57,7 +86,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
57
86
if did. is_local ( ) {
58
87
for def_id in prim. impls ( cx. tcx ) {
59
88
let impls = get_auto_trait_and_blanket_impls ( cx, def_id) ;
60
- new_items . extend ( impls. filter ( |i| cx. inlined . insert ( i. item_id ) ) ) ;
89
+ new_items_external . extend ( impls. filter ( |i| cx. inlined . insert ( i. item_id ) ) ) ;
61
90
}
62
91
}
63
92
}
@@ -71,6 +100,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
71
100
cx : & DocContext < ' _ > ,
72
101
map : & FxHashMap < DefId , & Type > ,
73
102
cleaner : & mut BadImplStripper < ' _ > ,
103
+ targets : & mut FxHashSet < DefId > ,
74
104
type_did : DefId ,
75
105
) {
76
106
if let Some ( target) = map. get ( & type_did) {
@@ -79,18 +109,18 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
79
109
cleaner. prims . insert ( target_prim) ;
80
110
} else if let Some ( target_did) = target. def_id ( & cx. cache ) {
81
111
// `impl Deref<Target = S> for S`
82
- if target_did == type_did {
112
+ if !targets . insert ( target_did) {
83
113
// Avoid infinite cycles
84
114
return ;
85
115
}
86
116
cleaner. items . insert ( target_did. into ( ) ) ;
87
- add_deref_target ( cx, map, cleaner, target_did) ;
117
+ add_deref_target ( cx, map, cleaner, targets , target_did) ;
88
118
}
89
119
}
90
120
}
91
121
92
122
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
93
- for it in & new_items {
123
+ for it in new_items_external . iter ( ) . chain ( new_items_local . iter ( ) ) {
94
124
if let ImplItem ( Impl { ref for_, ref trait_, ref items, .. } ) = * it. kind {
95
125
if trait_. as_ref ( ) . map ( |t| t. def_id ( ) ) == cx. tcx . lang_items ( ) . deref_trait ( )
96
126
&& cleaner. keep_impl ( for_, true )
@@ -114,15 +144,24 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
114
144
// `Deref` target type and the impl for type positions, this map of types is keyed by
115
145
// `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
116
146
if cleaner. keep_impl_with_def_id ( for_did. into ( ) ) {
117
- add_deref_target ( cx, & type_did_to_deref_target, & mut cleaner, for_did) ;
147
+ let mut targets = FxHashSet :: default ( ) ;
148
+ targets. insert ( for_did) ;
149
+ add_deref_target (
150
+ cx,
151
+ & type_did_to_deref_target,
152
+ & mut cleaner,
153
+ & mut targets,
154
+ for_did,
155
+ ) ;
118
156
}
119
157
}
120
158
}
121
159
}
122
160
}
123
161
}
124
162
125
- new_items. retain ( |it| {
163
+ // Filter out external items that are not needed
164
+ new_items_external. retain ( |it| {
126
165
if let ImplItem ( Impl { ref for_, ref trait_, ref kind, .. } ) = * it. kind {
127
166
cleaner. keep_impl (
128
167
for_,
@@ -134,37 +173,10 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
134
173
}
135
174
} ) ;
136
175
137
- // Local trait impls.
138
- cx. with_all_trait_impls ( |cx, all_trait_impls| {
139
- let _prof_timer = cx. tcx . sess . prof . generic_activity ( "build_local_trait_impls" ) ;
140
- let mut attr_buf = Vec :: new ( ) ;
141
- for & impl_def_id in all_trait_impls. iter ( ) . take_while ( |def_id| def_id. is_local ( ) ) {
142
- let mut parent = cx. tcx . parent ( impl_def_id) ;
143
- while let Some ( did) = parent {
144
- attr_buf. extend (
145
- cx. tcx
146
- . get_attrs ( did)
147
- . iter ( )
148
- . filter ( |attr| attr. has_name ( sym:: doc) )
149
- . filter ( |attr| {
150
- if let Some ( [ attr] ) = attr. meta_item_list ( ) . as_deref ( ) {
151
- attr. has_name ( sym:: cfg)
152
- } else {
153
- false
154
- }
155
- } )
156
- . cloned ( ) ,
157
- ) ;
158
- parent = cx. tcx . parent ( did) ;
159
- }
160
- inline:: build_impl ( cx, None , impl_def_id, Some ( & attr_buf) , & mut new_items) ;
161
- attr_buf. clear ( ) ;
162
- }
163
- } ) ;
164
-
165
176
if let ModuleItem ( Module { items, .. } ) = & mut * krate. module . kind {
166
177
items. extend ( synth_impls) ;
167
- items. extend ( new_items) ;
178
+ items. extend ( new_items_external) ;
179
+ items. extend ( new_items_local) ;
168
180
} else {
169
181
panic ! ( "collect-trait-impls can't run" ) ;
170
182
} ;
0 commit comments