@@ -579,12 +579,14 @@ pub(crate) fn build_index<'tcx>(
579579 let mut names = Vec :: with_capacity ( self . items . len ( ) ) ;
580580 let mut types = String :: with_capacity ( self . items . len ( ) ) ;
581581 let mut full_paths = Vec :: with_capacity ( self . items . len ( ) ) ;
582- let mut parents = Vec :: with_capacity ( self . items . len ( ) ) ;
582+ let mut parents = String :: with_capacity ( self . items . len ( ) ) ;
583+ let mut parents_backref_queue = VecDeque :: new ( ) ;
583584 let mut functions = String :: with_capacity ( self . items . len ( ) ) ;
584585 let mut deprecated = Vec :: with_capacity ( self . items . len ( ) ) ;
585586
586- let mut backref_queue = VecDeque :: new ( ) ;
587+ let mut type_backref_queue = VecDeque :: new ( ) ;
587588
589+ let mut last_name = None ;
588590 for ( index, item) in self . items . iter ( ) . enumerate ( ) {
589591 let n = item. ty as u8 ;
590592 let c = char:: try_from ( n + b'A' ) . expect ( "item types must fit in ASCII" ) ;
@@ -597,17 +599,36 @@ pub(crate) fn build_index<'tcx>(
597599 "`{}` is missing idx" ,
598600 item. name
599601 ) ;
600- // 0 is a sentinel, everything else is one-indexed
601- parents. push ( item. parent_idx . map ( |x| x + 1 ) . unwrap_or ( 0 ) ) ;
602+ assert ! ( parents_backref_queue. len( ) <= 16 ) ;
603+ let parent: i32 = item. parent_idx . map ( |x| x + 1 ) . unwrap_or ( 0 ) . try_into ( ) . unwrap ( ) ;
604+ if let Some ( idx) = parents_backref_queue. iter ( ) . position ( |p : & i32 | * p == parent) {
605+ parents. push (
606+ char:: try_from ( '0' as u32 + u32:: try_from ( idx) . unwrap ( ) )
607+ . expect ( "last possible value is '?'" ) ,
608+ ) ;
609+ } else if parent == 0 {
610+ write_vlqhex_to_string ( parent, & mut parents) ;
611+ } else {
612+ parents_backref_queue. push_front ( parent) ;
613+ write_vlqhex_to_string ( parent, & mut parents) ;
614+ if parents_backref_queue. len ( ) > 16 {
615+ parents_backref_queue. pop_back ( ) ;
616+ }
617+ }
602618
603- names. push ( item. name . as_str ( ) ) ;
619+ if Some ( item. name . as_str ( ) ) == last_name {
620+ names. push ( "" ) ;
621+ } else {
622+ names. push ( item. name . as_str ( ) ) ;
623+ last_name = Some ( item. name . as_str ( ) ) ;
624+ }
604625
605626 if !item. path . is_empty ( ) {
606627 full_paths. push ( ( index, & item. path ) ) ;
607628 }
608629
609630 match & item. search_type {
610- Some ( ty) => ty. write_to_string ( & mut functions, & mut backref_queue ) ,
631+ Some ( ty) => ty. write_to_string ( & mut functions, & mut type_backref_queue ) ,
611632 None => functions. push ( '`' ) ,
612633 }
613634
0 commit comments