@@ -1053,6 +1053,19 @@ fn render_assoc_items(
1053
1053
containing_item : & clean:: Item ,
1054
1054
it : DefId ,
1055
1055
what : AssocItemRender < ' _ > ,
1056
+ ) {
1057
+ let mut derefs = FxHashSet :: default ( ) ;
1058
+ derefs. insert ( it) ;
1059
+ render_assoc_items_inner ( w, cx, containing_item, it, what, & mut derefs)
1060
+ }
1061
+
1062
+ fn render_assoc_items_inner (
1063
+ w : & mut Buffer ,
1064
+ cx : & Context < ' _ > ,
1065
+ containing_item : & clean:: Item ,
1066
+ it : DefId ,
1067
+ what : AssocItemRender < ' _ > ,
1068
+ derefs : & mut FxHashSet < DefId > ,
1056
1069
) {
1057
1070
info ! ( "Documenting associated items of {:?}" , containing_item. name) ;
1058
1071
let cache = cx. cache ( ) ;
@@ -1072,12 +1085,18 @@ fn render_assoc_items(
1072
1085
RenderMode :: Normal
1073
1086
}
1074
1087
AssocItemRender :: DerefFor { trait_, type_, deref_mut_ } => {
1088
+ let id =
1089
+ cx. derive_id ( small_url_encode ( format ! ( "deref-methods-{:#}" , type_. print( cx) ) ) ) ;
1090
+ if let Some ( def_id) = type_. def_id ( cx. cache ( ) ) {
1091
+ cx. deref_id_map . borrow_mut ( ) . insert ( def_id, id. clone ( ) ) ;
1092
+ }
1075
1093
write ! (
1076
1094
w,
1077
- "<h2 id=\" deref-methods \" class=\" small-section-header\" >\
1095
+ "<h2 id=\" {id} \" class=\" small-section-header\" >\
1078
1096
<span>Methods from {trait_}<Target = {type_}></span>\
1079
- <a href=\" #deref-methods \" class=\" anchor\" ></a>\
1097
+ <a href=\" #{id} \" class=\" anchor\" ></a>\
1080
1098
</h2>",
1099
+ id = id,
1081
1100
trait_ = trait_. print( cx) ,
1082
1101
type_ = type_. print( cx) ,
1083
1102
) ;
@@ -1104,17 +1123,22 @@ fn render_assoc_items(
1104
1123
) ;
1105
1124
}
1106
1125
}
1107
- if let AssocItemRender :: DerefFor { .. } = what {
1108
- return ;
1109
- }
1126
+
1110
1127
if !traits. is_empty ( ) {
1111
1128
let deref_impl =
1112
1129
traits. iter ( ) . find ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) ) ;
1113
1130
if let Some ( impl_) = deref_impl {
1114
1131
let has_deref_mut =
1115
1132
traits. iter ( ) . any ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_mut_trait ( ) ) ;
1116
- render_deref_methods ( w, cx, impl_, containing_item, has_deref_mut) ;
1133
+ render_deref_methods ( w, cx, impl_, containing_item, has_deref_mut, derefs ) ;
1117
1134
}
1135
+
1136
+ // If we were already one level into rendering deref methods, we don't want to render
1137
+ // anything after recursing into any further deref methods above.
1138
+ if let AssocItemRender :: DerefFor { .. } = what {
1139
+ return ;
1140
+ }
1141
+
1118
1142
let ( synthetic, concrete) : ( Vec < & & Impl > , Vec < & & Impl > ) =
1119
1143
traits. iter ( ) . partition ( |t| t. inner_impl ( ) . synthetic ) ;
1120
1144
let ( blanket_impl, concrete) : ( Vec < & & Impl > , _ ) =
@@ -1166,6 +1190,7 @@ fn render_deref_methods(
1166
1190
impl_ : & Impl ,
1167
1191
container_item : & clean:: Item ,
1168
1192
deref_mut : bool ,
1193
+ derefs : & mut FxHashSet < DefId > ,
1169
1194
) {
1170
1195
let cache = cx. cache ( ) ;
1171
1196
let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
@@ -1187,16 +1212,16 @@ fn render_deref_methods(
1187
1212
if let Some ( did) = target. def_id ( cache) {
1188
1213
if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( cache) {
1189
1214
// `impl Deref<Target = S> for S`
1190
- if did == type_did {
1215
+ if did == type_did || !derefs . insert ( did ) {
1191
1216
// Avoid infinite cycles
1192
1217
return ;
1193
1218
}
1194
1219
}
1195
- render_assoc_items ( w, cx, container_item, did, what) ;
1220
+ render_assoc_items_inner ( w, cx, container_item, did, what, derefs ) ;
1196
1221
} else {
1197
1222
if let Some ( prim) = target. primitive_type ( ) {
1198
1223
if let Some ( & did) = cache. primitive_locations . get ( & prim) {
1199
- render_assoc_items ( w, cx, container_item, did, what) ;
1224
+ render_assoc_items_inner ( w, cx, container_item, did, what, derefs ) ;
1200
1225
}
1201
1226
}
1202
1227
}
@@ -1986,7 +2011,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
1986
2011
if let Some ( impl_) =
1987
2012
v. iter ( ) . find ( |i| i. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) )
1988
2013
{
1989
- sidebar_deref_methods ( cx, out, impl_, v) ;
2014
+ let mut derefs = FxHashSet :: default ( ) ;
2015
+ derefs. insert ( did) ;
2016
+ sidebar_deref_methods ( cx, out, impl_, v, & mut derefs) ;
1990
2017
}
1991
2018
1992
2019
let format_impls = |impls : Vec < & Impl > | {
@@ -2060,7 +2087,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
2060
2087
}
2061
2088
}
2062
2089
2063
- fn sidebar_deref_methods ( cx : & Context < ' _ > , out : & mut Buffer , impl_ : & Impl , v : & [ Impl ] ) {
2090
+ fn sidebar_deref_methods (
2091
+ cx : & Context < ' _ > ,
2092
+ out : & mut Buffer ,
2093
+ impl_ : & Impl ,
2094
+ v : & [ Impl ] ,
2095
+ derefs : & mut FxHashSet < DefId > ,
2096
+ ) {
2064
2097
let c = cx. cache ( ) ;
2065
2098
2066
2099
debug ! ( "found Deref: {:?}" , impl_) ;
@@ -2077,7 +2110,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
2077
2110
if let Some ( did) = target. def_id ( c) {
2078
2111
if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( c) {
2079
2112
// `impl Deref<Target = S> for S`
2080
- if did == type_did {
2113
+ if did == type_did || !derefs . insert ( did ) {
2081
2114
// Avoid infinite cycles
2082
2115
return ;
2083
2116
}
@@ -2101,9 +2134,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
2101
2134
} )
2102
2135
. collect :: < Vec < _ > > ( ) ;
2103
2136
if !ret. is_empty ( ) {
2137
+ let map;
2138
+ let id = if let Some ( target_def_id) = real_target. def_id ( c) {
2139
+ map = cx. deref_id_map . borrow ( ) ;
2140
+ map. get ( & target_def_id) . expect ( "Deref section without derived id" )
2141
+ } else {
2142
+ "deref-methods"
2143
+ } ;
2104
2144
write ! (
2105
2145
out,
2106
- "<h3 class=\" sidebar-title\" ><a href=\" #deref-methods\" >Methods from {}<Target={}></a></h3>" ,
2146
+ "<h3 class=\" sidebar-title\" ><a href=\" #{}\" >Methods from {}<Target={}></a></h3>" ,
2147
+ id,
2107
2148
Escape ( & format!( "{:#}" , impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) . print( cx) ) ) ,
2108
2149
Escape ( & format!( "{:#}" , real_target. print( cx) ) ) ,
2109
2150
) ;
@@ -2116,6 +2157,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
2116
2157
out. push_str ( "</div>" ) ;
2117
2158
}
2118
2159
}
2160
+
2161
+ // Recurse into any further impls that might exist for `target`
2162
+ if let Some ( target_did) = target. def_id_no_primitives ( ) {
2163
+ if let Some ( target_impls) = c. impls . get ( & target_did) {
2164
+ if let Some ( target_deref_impl) = target_impls. iter ( ) . find ( |i| {
2165
+ i. inner_impl ( )
2166
+ . trait_
2167
+ . as_ref ( )
2168
+ . map ( |t| Some ( t. def_id ( ) ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) )
2169
+ . unwrap_or ( false )
2170
+ } ) {
2171
+ sidebar_deref_methods ( cx, out, target_deref_impl, target_impls, derefs) ;
2172
+ }
2173
+ }
2174
+ }
2119
2175
}
2120
2176
}
2121
2177
0 commit comments