@@ -1054,6 +1054,19 @@ fn render_assoc_items(
1054
1054
containing_item : & clean:: Item ,
1055
1055
it : DefId ,
1056
1056
what : AssocItemRender < ' _ > ,
1057
+ ) {
1058
+ let mut derefs = FxHashSet :: default ( ) ;
1059
+ derefs. insert ( it) ;
1060
+ render_assoc_items_inner ( w, cx, containing_item, it, what, & mut derefs)
1061
+ }
1062
+
1063
+ fn render_assoc_items_inner (
1064
+ w : & mut Buffer ,
1065
+ cx : & Context < ' _ > ,
1066
+ containing_item : & clean:: Item ,
1067
+ it : DefId ,
1068
+ what : AssocItemRender < ' _ > ,
1069
+ derefs : & mut FxHashSet < DefId > ,
1057
1070
) {
1058
1071
info ! ( "Documenting associated items of {:?}" , containing_item. name) ;
1059
1072
let cache = cx. cache ( ) ;
@@ -1063,31 +1076,39 @@ fn render_assoc_items(
1063
1076
} ;
1064
1077
let ( non_trait, traits) : ( Vec < _ > , _ ) = v. iter ( ) . partition ( |i| i. inner_impl ( ) . trait_ . is_none ( ) ) ;
1065
1078
if !non_trait. is_empty ( ) {
1079
+ let mut tmp_buf = Buffer :: empty_from ( w) ;
1066
1080
let render_mode = match what {
1067
1081
AssocItemRender :: All => {
1068
- w . write_str (
1082
+ tmp_buf . write_str (
1069
1083
"<h2 id=\" implementations\" class=\" small-section-header\" >\
1070
1084
Implementations<a href=\" #implementations\" class=\" anchor\" ></a>\
1071
1085
</h2>",
1072
1086
) ;
1073
1087
RenderMode :: Normal
1074
1088
}
1075
1089
AssocItemRender :: DerefFor { trait_, type_, deref_mut_ } => {
1090
+ let id =
1091
+ cx. derive_id ( small_url_encode ( format ! ( "deref-methods-{:#}" , type_. print( cx) ) ) ) ;
1092
+ if let Some ( def_id) = type_. def_id ( cx. cache ( ) ) {
1093
+ cx. deref_id_map . borrow_mut ( ) . insert ( def_id, id. clone ( ) ) ;
1094
+ }
1076
1095
write ! (
1077
- w ,
1078
- "<h2 id=\" deref-methods \" class=\" small-section-header\" >\
1096
+ tmp_buf ,
1097
+ "<h2 id=\" {id} \" class=\" small-section-header\" >\
1079
1098
<span>Methods from {trait_}<Target = {type_}></span>\
1080
- <a href=\" #deref-methods \" class=\" anchor\" ></a>\
1099
+ <a href=\" #{id} \" class=\" anchor\" ></a>\
1081
1100
</h2>",
1101
+ id = id,
1082
1102
trait_ = trait_. print( cx) ,
1083
1103
type_ = type_. print( cx) ,
1084
1104
) ;
1085
1105
RenderMode :: ForDeref { mut_ : deref_mut_ }
1086
1106
}
1087
1107
} ;
1108
+ let mut impls_buf = Buffer :: empty_from ( w) ;
1088
1109
for i in & non_trait {
1089
1110
render_impl (
1090
- w ,
1111
+ & mut impls_buf ,
1091
1112
cx,
1092
1113
i,
1093
1114
containing_item,
@@ -1104,18 +1125,27 @@ fn render_assoc_items(
1104
1125
} ,
1105
1126
) ;
1106
1127
}
1128
+ if !impls_buf. is_empty ( ) {
1129
+ w. push_buffer ( tmp_buf) ;
1130
+ w. push_buffer ( impls_buf) ;
1131
+ }
1107
1132
}
1108
- if let AssocItemRender :: DerefFor { .. } = what {
1109
- return ;
1110
- }
1133
+
1111
1134
if !traits. is_empty ( ) {
1112
1135
let deref_impl =
1113
1136
traits. iter ( ) . find ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) ) ;
1114
1137
if let Some ( impl_) = deref_impl {
1115
1138
let has_deref_mut =
1116
1139
traits. iter ( ) . any ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_mut_trait ( ) ) ;
1117
- render_deref_methods ( w, cx, impl_, containing_item, has_deref_mut) ;
1140
+ render_deref_methods ( w, cx, impl_, containing_item, has_deref_mut, derefs) ;
1141
+ }
1142
+
1143
+ // If we were already one level into rendering deref methods, we don't want to render
1144
+ // anything after recursing into any further deref methods above.
1145
+ if let AssocItemRender :: DerefFor { .. } = what {
1146
+ return ;
1118
1147
}
1148
+
1119
1149
let ( synthetic, concrete) : ( Vec < & & Impl > , Vec < & & Impl > ) =
1120
1150
traits. iter ( ) . partition ( |t| t. inner_impl ( ) . synthetic ) ;
1121
1151
let ( blanket_impl, concrete) : ( Vec < & & Impl > , _ ) =
@@ -1167,6 +1197,7 @@ fn render_deref_methods(
1167
1197
impl_ : & Impl ,
1168
1198
container_item : & clean:: Item ,
1169
1199
deref_mut : bool ,
1200
+ derefs : & mut FxHashSet < DefId > ,
1170
1201
) {
1171
1202
let cache = cx. cache ( ) ;
1172
1203
let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
@@ -1188,16 +1219,16 @@ fn render_deref_methods(
1188
1219
if let Some ( did) = target. def_id ( cache) {
1189
1220
if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( cache) {
1190
1221
// `impl Deref<Target = S> for S`
1191
- if did == type_did {
1222
+ if did == type_did || !derefs . insert ( did ) {
1192
1223
// Avoid infinite cycles
1193
1224
return ;
1194
1225
}
1195
1226
}
1196
- render_assoc_items ( w, cx, container_item, did, what) ;
1227
+ render_assoc_items_inner ( w, cx, container_item, did, what, derefs ) ;
1197
1228
} else {
1198
1229
if let Some ( prim) = target. primitive_type ( ) {
1199
1230
if let Some ( & did) = cache. primitive_locations . get ( & prim) {
1200
- render_assoc_items ( w, cx, container_item, did, what) ;
1231
+ render_assoc_items_inner ( w, cx, container_item, did, what, derefs ) ;
1201
1232
}
1202
1233
}
1203
1234
}
@@ -1987,7 +2018,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
1987
2018
if let Some ( impl_) =
1988
2019
v. iter ( ) . find ( |i| i. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) )
1989
2020
{
1990
- sidebar_deref_methods ( cx, out, impl_, v) ;
2021
+ let mut derefs = FxHashSet :: default ( ) ;
2022
+ derefs. insert ( did) ;
2023
+ sidebar_deref_methods ( cx, out, impl_, v, & mut derefs) ;
1991
2024
}
1992
2025
1993
2026
let format_impls = |impls : Vec < & Impl > | {
@@ -2061,7 +2094,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
2061
2094
}
2062
2095
}
2063
2096
2064
- fn sidebar_deref_methods ( cx : & Context < ' _ > , out : & mut Buffer , impl_ : & Impl , v : & [ Impl ] ) {
2097
+ fn sidebar_deref_methods (
2098
+ cx : & Context < ' _ > ,
2099
+ out : & mut Buffer ,
2100
+ impl_ : & Impl ,
2101
+ v : & [ Impl ] ,
2102
+ derefs : & mut FxHashSet < DefId > ,
2103
+ ) {
2065
2104
let c = cx. cache ( ) ;
2066
2105
2067
2106
debug ! ( "found Deref: {:?}" , impl_) ;
@@ -2078,7 +2117,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
2078
2117
if let Some ( did) = target. def_id ( c) {
2079
2118
if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( c) {
2080
2119
// `impl Deref<Target = S> for S`
2081
- if did == type_did {
2120
+ if did == type_did || !derefs . insert ( did ) {
2082
2121
// Avoid infinite cycles
2083
2122
return ;
2084
2123
}
@@ -2102,9 +2141,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
2102
2141
} )
2103
2142
. collect :: < Vec < _ > > ( ) ;
2104
2143
if !ret. is_empty ( ) {
2144
+ let map;
2145
+ let id = if let Some ( target_def_id) = real_target. def_id ( c) {
2146
+ map = cx. deref_id_map . borrow ( ) ;
2147
+ map. get ( & target_def_id) . expect ( "Deref section without derived id" )
2148
+ } else {
2149
+ "deref-methods"
2150
+ } ;
2105
2151
write ! (
2106
2152
out,
2107
- "<h3 class=\" sidebar-title\" ><a href=\" #deref-methods\" >Methods from {}<Target={}></a></h3>" ,
2153
+ "<h3 class=\" sidebar-title\" ><a href=\" #{}\" >Methods from {}<Target={}></a></h3>" ,
2154
+ id,
2108
2155
Escape ( & format!( "{:#}" , impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) . print( cx) ) ) ,
2109
2156
Escape ( & format!( "{:#}" , real_target. print( cx) ) ) ,
2110
2157
) ;
@@ -2117,6 +2164,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
2117
2164
out. push_str ( "</div>" ) ;
2118
2165
}
2119
2166
}
2167
+
2168
+ // Recurse into any further impls that might exist for `target`
2169
+ if let Some ( target_did) = target. def_id_no_primitives ( ) {
2170
+ if let Some ( target_impls) = c. impls . get ( & target_did) {
2171
+ if let Some ( target_deref_impl) = target_impls. iter ( ) . find ( |i| {
2172
+ i. inner_impl ( )
2173
+ . trait_
2174
+ . as_ref ( )
2175
+ . map ( |t| Some ( t. def_id ( ) ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) )
2176
+ . unwrap_or ( false )
2177
+ } ) {
2178
+ sidebar_deref_methods ( cx, out, target_deref_impl, target_impls, derefs) ;
2179
+ }
2180
+ }
2181
+ }
2120
2182
}
2121
2183
}
2122
2184
0 commit comments