@@ -115,6 +115,9 @@ crate struct Context<'tcx> {
115115 crate render_redirect_pages : bool ,
116116 /// The map used to ensure all generated 'id=' attributes are unique.
117117 id_map : Rc < RefCell < IdMap > > ,
118+ /// Tracks section IDs for `Deref` targets so they match in both the main
119+ /// body and the sidebar.
120+ deref_id_map : Rc < RefCell < FxHashMap < DefId , String > > > ,
118121 crate shared : Arc < SharedContext < ' tcx > > ,
119122 all : Rc < RefCell < AllTypes > > ,
120123 /// Storage for the errors produced while generating documentation so they
@@ -372,7 +375,6 @@ crate fn initial_ids() -> Vec<String> {
372375 "implementors-list" ,
373376 "synthetic-implementors-list" ,
374377 "methods" ,
375- "deref-methods" ,
376378 "implementations" ,
377379 ]
378380 . iter ( )
@@ -506,6 +508,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
506508 dst,
507509 render_redirect_pages : false ,
508510 id_map : Rc :: new ( RefCell :: new ( id_map) ) ,
511+ deref_id_map : Rc :: new ( RefCell :: new ( FxHashMap :: default ( ) ) ) ,
509512 shared : Arc :: new ( scx) ,
510513 all : Rc :: new ( RefCell :: new ( AllTypes :: new ( ) ) ) ,
511514 errors : Rc :: new ( receiver) ,
@@ -3517,14 +3520,18 @@ fn render_assoc_items(
35173520 RenderMode :: Normal
35183521 }
35193522 AssocItemRender :: DerefFor { trait_, type_, deref_mut_ } => {
3523+ let id =
3524+ cx. derive_id ( small_url_encode ( & format ! ( "deref-methods-{:#}" , type_. print( ) ) ) ) ;
3525+ cx. deref_id_map . borrow_mut ( ) . insert ( type_. def_id ( ) . unwrap ( ) , id. clone ( ) ) ;
35203526 write ! (
35213527 w,
3522- "<h2 id=\" deref-methods \" class=\" small-section-header\" >\
3523- Methods from {}<Target = {}>\
3524- <a href=\" #deref-methods \" class=\" anchor\" ></a>\
3528+ "<h2 id=\" {id} \" class=\" small-section-header\" >\
3529+ Methods from {trait_ }<Target = {type_ }>\
3530+ <a href=\" #{id} \" class=\" anchor\" ></a>\
35253531 </h2>",
3526- trait_. print( ) ,
3527- type_. print( )
3532+ id = id,
3533+ trait_ = trait_. print( ) ,
3534+ type_ = type_. print( ) ,
35283535 ) ;
35293536 RenderMode :: ForDeref { mut_ : deref_mut_ }
35303537 }
@@ -4175,14 +4182,14 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer, cache:
41754182 ) ;
41764183 }
41774184 match * it. kind {
4178- clean:: StructItem ( ref s) => sidebar_struct ( buffer, it, s) ,
4179- clean:: TraitItem ( ref t) => sidebar_trait ( buffer, it, t) ,
4180- clean:: PrimitiveItem ( _) => sidebar_primitive ( buffer, it) ,
4181- clean:: UnionItem ( ref u) => sidebar_union ( buffer, it, u) ,
4182- clean:: EnumItem ( ref e) => sidebar_enum ( buffer, it, e) ,
4183- clean:: TypedefItem ( _, _) => sidebar_typedef ( buffer, it) ,
4185+ clean:: StructItem ( ref s) => sidebar_struct ( cx , buffer, it, s) ,
4186+ clean:: TraitItem ( ref t) => sidebar_trait ( cx , buffer, it, t) ,
4187+ clean:: PrimitiveItem ( _) => sidebar_primitive ( cx , buffer, it) ,
4188+ clean:: UnionItem ( ref u) => sidebar_union ( cx , buffer, it, u) ,
4189+ clean:: EnumItem ( ref e) => sidebar_enum ( cx , buffer, it, e) ,
4190+ clean:: TypedefItem ( _, _) => sidebar_typedef ( cx , buffer, it) ,
41844191 clean:: ModuleItem ( ref m) => sidebar_module ( buffer, & m. items ) ,
4185- clean:: ForeignTypeItem => sidebar_foreign_type ( buffer, it) ,
4192+ clean:: ForeignTypeItem => sidebar_foreign_type ( cx , buffer, it) ,
41864193 _ => ( ) ,
41874194 }
41884195
@@ -4283,7 +4290,7 @@ fn small_url_encode(s: &str) -> String {
42834290 . replace ( "\" " , "%22" )
42844291}
42854292
4286- fn sidebar_assoc_items ( it : & clean:: Item ) -> String {
4293+ fn sidebar_assoc_items ( cx : & Context < ' _ > , it : & clean:: Item ) -> String {
42874294 let mut out = String :: new ( ) ;
42884295 let c = cache ( ) ;
42894296 if let Some ( v) = c. impls . get ( & it. def_id ) {
@@ -4313,7 +4320,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
43134320 . filter ( |i| i. inner_impl ( ) . trait_ . is_some ( ) )
43144321 . find ( |i| i. inner_impl ( ) . trait_ . def_id ( ) == c. deref_trait_did )
43154322 {
4316- out. push_str ( & sidebar_deref_methods ( impl_, v) ) ;
4323+ out. push_str ( & sidebar_deref_methods ( cx , impl_, v) ) ;
43174324 }
43184325 let format_impls = |impls : Vec < & Impl > | {
43194326 let mut links = FxHashSet :: default ( ) ;
@@ -4381,7 +4388,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
43814388 out
43824389}
43834390
4384- fn sidebar_deref_methods ( impl_ : & Impl , v : & Vec < Impl > ) -> String {
4391+ fn sidebar_deref_methods ( cx : & Context < ' _ > , impl_ : & Impl , v : & Vec < Impl > ) -> String {
43854392 let mut out = String :: new ( ) ;
43864393 let c = cache ( ) ;
43874394
@@ -4408,22 +4415,26 @@ fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
44084415 . and_then ( |did| c. impls . get ( & did) ) ;
44094416 if let Some ( impls) = inner_impl {
44104417 debug ! ( "found inner_impl: {:?}" , impls) ;
4411- out. push_str ( "<a class=\" sidebar-title\" href=\" #deref-methods\" >" ) ;
4412- out. push_str ( & format ! (
4413- "Methods from {}<Target={}>" ,
4414- Escape ( & format!( "{:#}" , impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) . print( ) ) ) ,
4415- Escape ( & format!( "{:#}" , real_target. print( ) ) )
4416- ) ) ;
4417- out. push_str ( "</a>" ) ;
44184418 let mut used_links = FxHashSet :: default ( ) ;
44194419 let mut ret = impls
44204420 . iter ( )
44214421 . filter ( |i| i. inner_impl ( ) . trait_ . is_none ( ) )
44224422 . flat_map ( |i| get_methods ( i. inner_impl ( ) , true , & mut used_links, deref_mut) )
44234423 . collect :: < Vec < _ > > ( ) ;
4424- // We want links' order to be reproducible so we don't use unstable sort.
4425- ret. sort ( ) ;
44264424 if !ret. is_empty ( ) {
4425+ let deref_id_map = cx. deref_id_map . borrow ( ) ;
4426+ let id = deref_id_map
4427+ . get ( & real_target. def_id ( ) . unwrap ( ) )
4428+ . expect ( "Deref section without derived id" ) ;
4429+ out. push_str ( & format ! ( "<a class=\" sidebar-title\" href=\" #{}\" >" , id) ) ;
4430+ out. push_str ( & format ! (
4431+ "Methods from {}<Target={}>" ,
4432+ Escape ( & format!( "{:#}" , impl_. inner_impl( ) . trait_. as_ref( ) . unwrap( ) . print( ) ) ) ,
4433+ Escape ( & format!( "{:#}" , real_target. print( ) ) )
4434+ ) ) ;
4435+ out. push_str ( "</a>" ) ;
4436+ // We want links' order to be reproducible so we don't use unstable sort.
4437+ ret. sort ( ) ;
44274438 out. push_str ( & format ! ( "<div class=\" sidebar-links\" >{}</div>" , ret. join( "" ) ) ) ;
44284439 }
44294440 }
@@ -4443,7 +4454,7 @@ fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
44434454 return out;
44444455 }
44454456 }
4446- out. push_str ( & sidebar_deref_methods ( target_deref_impl, target_impls) ) ;
4457+ out. push_str ( & sidebar_deref_methods ( cx , target_deref_impl, target_impls) ) ;
44474458 }
44484459 }
44494460 }
@@ -4452,7 +4463,7 @@ fn sidebar_deref_methods(impl_: &Impl, v: &Vec<Impl>) -> String {
44524463 out
44534464}
44544465
4455- fn sidebar_struct ( buf : & mut Buffer , it : & clean:: Item , s : & clean:: Struct ) {
4466+ fn sidebar_struct ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item , s : & clean:: Struct ) {
44564467 let mut sidebar = String :: new ( ) ;
44574468 let fields = get_struct_fields_name ( & s. fields ) ;
44584469
@@ -4466,7 +4477,7 @@ fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
44664477 }
44674478 }
44684479
4469- sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
4480+ sidebar. push_str ( & sidebar_assoc_items ( cx , it) ) ;
44704481
44714482 if !sidebar. is_empty ( ) {
44724483 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar) ;
@@ -4497,7 +4508,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool {
44974508 i. polarity == Some ( clean:: ImplPolarity :: Negative )
44984509}
44994510
4500- fn sidebar_trait ( buf : & mut Buffer , it : & clean:: Item , t : & clean:: Trait ) {
4511+ fn sidebar_trait ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item , t : & clean:: Trait ) {
45014512 let mut sidebar = String :: new ( ) ;
45024513
45034514 let mut types = t
@@ -4597,7 +4608,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
45974608 }
45984609 }
45994610
4600- sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
4611+ sidebar. push_str ( & sidebar_assoc_items ( cx , it) ) ;
46014612
46024613 sidebar. push_str ( "<a class=\" sidebar-title\" href=\" #implementors\" >Implementors</a>" ) ;
46034614 if t. is_auto {
@@ -4610,16 +4621,16 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
46104621 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar)
46114622}
46124623
4613- fn sidebar_primitive ( buf : & mut Buffer , it : & clean:: Item ) {
4614- let sidebar = sidebar_assoc_items ( it) ;
4624+ fn sidebar_primitive ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item ) {
4625+ let sidebar = sidebar_assoc_items ( cx , it) ;
46154626
46164627 if !sidebar. is_empty ( ) {
46174628 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar) ;
46184629 }
46194630}
46204631
4621- fn sidebar_typedef ( buf : & mut Buffer , it : & clean:: Item ) {
4622- let sidebar = sidebar_assoc_items ( it) ;
4632+ fn sidebar_typedef ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item ) {
4633+ let sidebar = sidebar_assoc_items ( cx , it) ;
46234634
46244635 if !sidebar. is_empty ( ) {
46254636 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar) ;
@@ -4641,7 +4652,7 @@ fn get_struct_fields_name(fields: &[clean::Item]) -> String {
46414652 fields. join ( "" )
46424653}
46434654
4644- fn sidebar_union ( buf : & mut Buffer , it : & clean:: Item , u : & clean:: Union ) {
4655+ fn sidebar_union ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item , u : & clean:: Union ) {
46454656 let mut sidebar = String :: new ( ) ;
46464657 let fields = get_struct_fields_name ( & u. fields ) ;
46474658
@@ -4653,14 +4664,14 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
46534664 ) ) ;
46544665 }
46554666
4656- sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
4667+ sidebar. push_str ( & sidebar_assoc_items ( cx , it) ) ;
46574668
46584669 if !sidebar. is_empty ( ) {
46594670 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar) ;
46604671 }
46614672}
46624673
4663- fn sidebar_enum ( buf : & mut Buffer , it : & clean:: Item , e : & clean:: Enum ) {
4674+ fn sidebar_enum ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item , e : & clean:: Enum ) {
46644675 let mut sidebar = String :: new ( ) ;
46654676
46664677 let mut variants = e
@@ -4680,7 +4691,7 @@ fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
46804691 ) ) ;
46814692 }
46824693
4683- sidebar. push_str ( & sidebar_assoc_items ( it) ) ;
4694+ sidebar. push_str ( & sidebar_assoc_items ( cx , it) ) ;
46844695
46854696 if !sidebar. is_empty ( ) {
46864697 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar) ;
@@ -4769,8 +4780,8 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
47694780 }
47704781}
47714782
4772- fn sidebar_foreign_type ( buf : & mut Buffer , it : & clean:: Item ) {
4773- let sidebar = sidebar_assoc_items ( it) ;
4783+ fn sidebar_foreign_type ( cx : & Context < ' _ > , buf : & mut Buffer , it : & clean:: Item ) {
4784+ let sidebar = sidebar_assoc_items ( cx , it) ;
47744785 if !sidebar. is_empty ( ) {
47754786 write ! ( buf, "<div class=\" block items\" >{}</div>" , sidebar) ;
47764787 }
0 commit comments