@@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
15621562 in_value : bool ,
15631563 pub print_alloc_ids : bool ,
15641564
1565+ // set of all named (non-anonymous) region names
15651566 used_region_names : FxHashSet < Symbol > ,
1567+
15661568 region_index : usize ,
15671569 binder_depth : usize ,
15681570 printed_type_count : usize ,
@@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
21182120 where
21192121 T : Print < ' tcx , Self , Output = Self , Error = fmt:: Error > + TypeFoldable < ' tcx > ,
21202122 {
2121- fn name_by_region_index ( index : usize ) -> Symbol {
2122- match index {
2123- 0 => Symbol :: intern ( "'r" ) ,
2124- 1 => Symbol :: intern ( "'s" ) ,
2125- i => Symbol :: intern ( & format ! ( "'t{}" , i - 2 ) ) ,
2123+ fn name_by_region_index (
2124+ index : usize ,
2125+ available_names : & mut Vec < Symbol > ,
2126+ num_available : usize ,
2127+ ) -> Symbol {
2128+ if let Some ( name) = available_names. pop ( ) {
2129+ name
2130+ } else {
2131+ Symbol :: intern ( & format ! ( "'z{}" , index - num_available) )
21262132 }
21272133 }
21282134
2135+ debug ! ( "name_all_regions" ) ;
2136+
21292137 // Replace any anonymous late-bound regions with named
21302138 // variants, using new unique identifiers, so that we can
21312139 // clearly differentiate between named and unnamed regions in
21322140 // the output. We'll probably want to tweak this over time to
21332141 // decide just how much information to give.
21342142 if self . binder_depth == 0 {
2135- self . prepare_late_bound_region_info ( value) ;
2143+ self . prepare_region_info ( value) ;
21362144 }
21372145
2146+ debug ! ( "self.used_region_names: {:?}" , & self . used_region_names) ;
2147+
21382148 let mut empty = true ;
21392149 let mut start_or_continue = |cx : & mut Self , start : & str , cont : & str | {
21402150 let w = if empty {
@@ -2151,13 +2161,24 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
21512161
21522162 define_scoped_cx ! ( self ) ;
21532163
2164+ let possible_names =
2165+ ( 'a' ..='z' ) . rev ( ) . map ( |s| Symbol :: intern ( & format ! ( "'{s}" ) ) ) . collect :: < Vec < _ > > ( ) ;
2166+
2167+ let mut available_names = possible_names
2168+ . into_iter ( )
2169+ . filter ( |name| !self . used_region_names . contains ( & name) )
2170+ . collect :: < Vec < _ > > ( ) ;
2171+ debug ! ( ?available_names) ;
2172+ let num_available = available_names. len ( ) ;
2173+
21542174 let mut region_index = self . region_index ;
2155- let mut next_name = |this : & Self | loop {
2156- let name = name_by_region_index ( region_index) ;
2175+ let mut next_name = |this : & Self | {
2176+ let name = name_by_region_index ( region_index, & mut available_names, num_available) ;
2177+ debug ! ( ?name) ;
21572178 region_index += 1 ;
2158- if ! this. used_region_names . contains ( & name) {
2159- break name ;
2160- }
2179+ assert ! ( ! this. used_region_names. contains( & name) ) ;
2180+
2181+ name
21612182 } ;
21622183
21632184 // If we want to print verbosely, then print *all* binders, even if they
@@ -2178,6 +2199,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
21782199 ty:: BrAnon ( _) | ty:: BrEnv => {
21792200 start_or_continue ( & mut self , "for<" , ", " ) ;
21802201 let name = next_name ( & self ) ;
2202+ debug ! ( ?name) ;
21812203 do_continue ( & mut self , name) ;
21822204 ty:: BrNamed ( CRATE_DEF_ID . to_def_id ( ) , name)
21832205 }
@@ -2271,29 +2293,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
22712293 Ok ( inner)
22722294 }
22732295
2274- fn prepare_late_bound_region_info < T > ( & mut self , value : & ty:: Binder < ' tcx , T > )
2296+ fn prepare_region_info < T > ( & mut self , value : & ty:: Binder < ' tcx , T > )
22752297 where
22762298 T : TypeVisitable < ' tcx > ,
22772299 {
2278- struct LateBoundRegionNameCollector < ' a , ' tcx > {
2279- used_region_names : & ' a mut FxHashSet < Symbol > ,
2300+ struct RegionNameCollector < ' tcx > {
2301+ used_region_names : FxHashSet < Symbol > ,
22802302 type_collector : SsoHashSet < Ty < ' tcx > > ,
22812303 }
22822304
2283- impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for LateBoundRegionNameCollector < ' _ , ' tcx > {
2305+ impl < ' tcx > RegionNameCollector < ' tcx > {
2306+ fn new ( ) -> Self {
2307+ RegionNameCollector {
2308+ used_region_names : Default :: default ( ) ,
2309+ type_collector : SsoHashSet :: new ( ) ,
2310+ }
2311+ }
2312+ }
2313+
2314+ impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for RegionNameCollector < ' tcx > {
22842315 type BreakTy = ( ) ;
22852316
22862317 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
22872318 trace ! ( "address: {:p}" , r. 0.0 ) ;
2288- if let ty:: ReLateBound ( _, ty:: BoundRegion { kind : ty:: BrNamed ( _, name) , .. } ) = * r {
2289- self . used_region_names . insert ( name) ;
2290- } else if let ty:: RePlaceholder ( ty:: PlaceholderRegion {
2291- name : ty:: BrNamed ( _, name) ,
2292- ..
2293- } ) = * r
2294- {
2319+
2320+ // Collect all named lifetimes. These allow us to prevent duplication
2321+ // of already existing lifetime names when introducing names for
2322+ // anonymous late-bound regions.
2323+ if let Some ( name) = r. get_name ( ) {
22952324 self . used_region_names . insert ( name) ;
22962325 }
2326+
22972327 r. super_visit_with ( self )
22982328 }
22992329
@@ -2309,12 +2339,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
23092339 }
23102340 }
23112341
2312- self . used_region_names . clear ( ) ;
2313- let mut collector = LateBoundRegionNameCollector {
2314- used_region_names : & mut self . used_region_names ,
2315- type_collector : SsoHashSet :: new ( ) ,
2316- } ;
2342+ let mut collector = RegionNameCollector :: new ( ) ;
23172343 value. visit_with ( & mut collector) ;
2344+ self . used_region_names = collector. used_region_names ;
23182345 self . region_index = 0 ;
23192346 }
23202347}
0 commit comments