@@ -1053,6 +1053,19 @@ fn render_assoc_items(
10531053 containing_item : & clean:: Item ,
10541054 it : DefId ,
10551055 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 > ,
10561069) {
10571070 info ! ( "Documenting associated items of {:?}" , containing_item. name) ;
10581071 let cache = cx. cache ( ) ;
@@ -1072,12 +1085,18 @@ fn render_assoc_items(
10721085 RenderMode :: Normal
10731086 }
10741087 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+ }
10751093 write ! (
10761094 w,
1077- "<h2 id=\" deref-methods \" class=\" small-section-header\" >\
1095+ "<h2 id=\" {id} \" class=\" small-section-header\" >\
10781096 <span>Methods from {trait_}<Target = {type_}></span>\
1079- <a href=\" #deref-methods \" class=\" anchor\" ></a>\
1097+ <a href=\" #{id} \" class=\" anchor\" ></a>\
10801098 </h2>",
1099+ id = id,
10811100 trait_ = trait_. print( cx) ,
10821101 type_ = type_. print( cx) ,
10831102 ) ;
@@ -1104,17 +1123,22 @@ fn render_assoc_items(
11041123 ) ;
11051124 }
11061125 }
1107- if let AssocItemRender :: DerefFor { .. } = what {
1108- return ;
1109- }
1126+
11101127 if !traits. is_empty ( ) {
11111128 let deref_impl =
11121129 traits. iter ( ) . find ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) ) ;
11131130 if let Some ( impl_) = deref_impl {
11141131 let has_deref_mut =
11151132 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 ) ;
11171134 }
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+
11181142 let ( synthetic, concrete) : ( Vec < & & Impl > , Vec < & & Impl > ) =
11191143 traits. iter ( ) . partition ( |t| t. inner_impl ( ) . synthetic ) ;
11201144 let ( blanket_impl, concrete) : ( Vec < & & Impl > , _ ) =
@@ -1166,6 +1190,7 @@ fn render_deref_methods(
11661190 impl_ : & Impl ,
11671191 container_item : & clean:: Item ,
11681192 deref_mut : bool ,
1193+ derefs : & mut FxHashSet < DefId > ,
11691194) {
11701195 let cache = cx. cache ( ) ;
11711196 let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
@@ -1187,16 +1212,16 @@ fn render_deref_methods(
11871212 if let Some ( did) = target. def_id ( cache) {
11881213 if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( cache) {
11891214 // `impl Deref<Target = S> for S`
1190- if did == type_did {
1215+ if did == type_did || !derefs . insert ( did ) {
11911216 // Avoid infinite cycles
11921217 return ;
11931218 }
11941219 }
1195- render_assoc_items ( w, cx, container_item, did, what) ;
1220+ render_assoc_items_inner ( w, cx, container_item, did, what, derefs ) ;
11961221 } else {
11971222 if let Some ( prim) = target. primitive_type ( ) {
11981223 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 ) ;
12001225 }
12011226 }
12021227 }
@@ -1986,7 +2011,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
19862011 if let Some ( impl_) =
19872012 v. iter ( ) . find ( |i| i. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) )
19882013 {
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) ;
19902017 }
19912018
19922019 let format_impls = |impls : Vec < & Impl > | {
@@ -2060,7 +2087,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
20602087 }
20612088}
20622089
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+ ) {
20642097 let c = cx. cache ( ) ;
20652098
20662099 debug ! ( "found Deref: {:?}" , impl_) ;
@@ -2077,7 +2110,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
20772110 if let Some ( did) = target. def_id ( c) {
20782111 if let Some ( type_did) = impl_. inner_impl ( ) . for_ . def_id ( c) {
20792112 // `impl Deref<Target = S> for S`
2080- if did == type_did {
2113+ if did == type_did || !derefs . insert ( did ) {
20812114 // Avoid infinite cycles
20822115 return ;
20832116 }
@@ -2101,9 +2134,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
21012134 } )
21022135 . collect :: < Vec < _ > > ( ) ;
21032136 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+ } ;
21042144 write ! (
21052145 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,
21072148 Escape ( & format!( "{:#}" , impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) . print( cx) ) ) ,
21082149 Escape ( & format!( "{:#}" , real_target. print( cx) ) ) ,
21092150 ) ;
@@ -2116,6 +2157,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
21162157 out. push_str ( "</div>" ) ;
21172158 }
21182159 }
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+ }
21192175 }
21202176}
21212177
0 commit comments