@@ -1054,6 +1054,19 @@ fn render_assoc_items(
10541054 containing_item : & clean:: Item ,
10551055 it : DefId ,
10561056 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 > ,
10571070) {
10581071 info ! ( "Documenting associated items of {:?}" , containing_item. name) ;
10591072 let cache = cx. cache ( ) ;
@@ -1063,31 +1076,39 @@ fn render_assoc_items(
10631076 } ;
10641077 let ( non_trait, traits) : ( Vec < _ > , _ ) = v. iter ( ) . partition ( |i| i. inner_impl ( ) . trait_ . is_none ( ) ) ;
10651078 if !non_trait. is_empty ( ) {
1079+ let mut tmp_buf = Buffer :: empty_from ( w) ;
10661080 let render_mode = match what {
10671081 AssocItemRender :: All => {
1068- w . write_str (
1082+ tmp_buf . write_str (
10691083 "<h2 id=\" implementations\" class=\" small-section-header\" >\
10701084 Implementations<a href=\" #implementations\" class=\" anchor\" ></a>\
10711085 </h2>",
10721086 ) ;
10731087 RenderMode :: Normal
10741088 }
10751089 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+ }
10761095 write ! (
1077- w ,
1078- "<h2 id=\" deref-methods \" class=\" small-section-header\" >\
1096+ tmp_buf ,
1097+ "<h2 id=\" {id} \" class=\" small-section-header\" >\
10791098 <span>Methods from {trait_}<Target = {type_}></span>\
1080- <a href=\" #deref-methods \" class=\" anchor\" ></a>\
1099+ <a href=\" #{id} \" class=\" anchor\" ></a>\
10811100 </h2>",
1101+ id = id,
10821102 trait_ = trait_. print( cx) ,
10831103 type_ = type_. print( cx) ,
10841104 ) ;
10851105 RenderMode :: ForDeref { mut_ : deref_mut_ }
10861106 }
10871107 } ;
1108+ let mut impls_buf = Buffer :: empty_from ( w) ;
10881109 for i in & non_trait {
10891110 render_impl (
1090- w ,
1111+ & mut impls_buf ,
10911112 cx,
10921113 i,
10931114 containing_item,
@@ -1104,18 +1125,27 @@ fn render_assoc_items(
11041125 } ,
11051126 ) ;
11061127 }
1128+ if !impls_buf. is_empty ( ) {
1129+ w. push_buffer ( tmp_buf) ;
1130+ w. push_buffer ( impls_buf) ;
1131+ }
11071132 }
1108- if let AssocItemRender :: DerefFor { .. } = what {
1109- return ;
1110- }
1133+
11111134 if !traits. is_empty ( ) {
11121135 let deref_impl =
11131136 traits. iter ( ) . find ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) ) ;
11141137 if let Some ( impl_) = deref_impl {
11151138 let has_deref_mut =
11161139 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 ;
11181147 }
1148+
11191149 let ( synthetic, concrete) : ( Vec < & & Impl > , Vec < & & Impl > ) =
11201150 traits. iter ( ) . partition ( |t| t. inner_impl ( ) . synthetic ) ;
11211151 let ( blanket_impl, concrete) : ( Vec < & & Impl > , _ ) =
@@ -1167,6 +1197,7 @@ fn render_deref_methods(
11671197 impl_ : & Impl ,
11681198 container_item : & clean:: Item ,
11691199 deref_mut : bool ,
1200+ derefs : & mut FxHashSet < DefId > ,
11701201) {
11711202 let cache = cx. cache ( ) ;
11721203 let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
@@ -1188,16 +1219,16 @@ fn render_deref_methods(
11881219 if let Some ( did) = target. def_id ( cache) {
11891220 if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( cache) {
11901221 // `impl Deref<Target = S> for S`
1191- if did == type_did {
1222+ if did == type_did || !derefs . insert ( did ) {
11921223 // Avoid infinite cycles
11931224 return ;
11941225 }
11951226 }
1196- render_assoc_items ( w, cx, container_item, did, what) ;
1227+ render_assoc_items_inner ( w, cx, container_item, did, what, derefs ) ;
11971228 } else {
11981229 if let Some ( prim) = target. primitive_type ( ) {
11991230 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 ) ;
12011232 }
12021233 }
12031234 }
@@ -1987,7 +2018,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
19872018 if let Some ( impl_) =
19882019 v. iter ( ) . find ( |i| i. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) )
19892020 {
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) ;
19912024 }
19922025
19932026 let format_impls = |impls : Vec < & Impl > | {
@@ -2061,7 +2094,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
20612094 }
20622095}
20632096
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+ ) {
20652104 let c = cx. cache ( ) ;
20662105
20672106 debug ! ( "found Deref: {:?}" , impl_) ;
@@ -2078,7 +2117,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
20782117 if let Some ( did) = target. def_id ( c) {
20792118 if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( c) {
20802119 // `impl Deref<Target = S> for S`
2081- if did == type_did {
2120+ if did == type_did || !derefs . insert ( did ) {
20822121 // Avoid infinite cycles
20832122 return ;
20842123 }
@@ -2102,9 +2141,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
21022141 } )
21032142 . collect :: < Vec < _ > > ( ) ;
21042143 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+ } ;
21052151 write ! (
21062152 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,
21082155 Escape ( & format!( "{:#}" , impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) . print( cx) ) ) ,
21092156 Escape ( & format!( "{:#}" , real_target. print( cx) ) ) ,
21102157 ) ;
@@ -2117,6 +2164,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
21172164 out. push_str ( "</div>" ) ;
21182165 }
21192166 }
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+ }
21202182 }
21212183}
21222184
0 commit comments