@@ -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,39 @@ 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 ! (
603+ parents_backref_queue. len( ) <= 16 ,
604+ "the string encoding only supports 16 slots of lookback"
605+ ) ;
606+ let parent: i32 = item. parent_idx . map ( |x| x + 1 ) . unwrap_or ( 0 ) . try_into ( ) . unwrap ( ) ;
607+ if let Some ( idx) = parents_backref_queue. iter ( ) . position ( |p : & i32 | * p == parent) {
608+ parents. push (
609+ char:: try_from ( '0' as u32 + u32:: try_from ( idx) . unwrap ( ) )
610+ . expect ( "last possible value is '?'" ) ,
611+ ) ;
612+ } else if parent == 0 {
613+ write_vlqhex_to_string ( parent, & mut parents) ;
614+ } else {
615+ parents_backref_queue. push_front ( parent) ;
616+ write_vlqhex_to_string ( parent, & mut parents) ;
617+ if parents_backref_queue. len ( ) > 16 {
618+ parents_backref_queue. pop_back ( ) ;
619+ }
620+ }
602621
603- names. push ( item. name . as_str ( ) ) ;
622+ if Some ( item. name . as_str ( ) ) == last_name {
623+ names. push ( "" ) ;
624+ } else {
625+ names. push ( item. name . as_str ( ) ) ;
626+ last_name = Some ( item. name . as_str ( ) ) ;
627+ }
604628
605629 if !item. path . is_empty ( ) {
606630 full_paths. push ( ( index, & item. path ) ) ;
607631 }
608632
609633 match & item. search_type {
610- Some ( ty) => ty. write_to_string ( & mut functions, & mut backref_queue ) ,
634+ Some ( ty) => ty. write_to_string ( & mut functions, & mut type_backref_queue ) ,
611635 None => functions. push ( '`' ) ,
612636 }
613637
0 commit comments