@@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
1562
1562
in_value : bool ,
1563
1563
pub print_alloc_ids : bool ,
1564
1564
1565
+ // set of all named (non-anonymous) region names
1565
1566
used_region_names : FxHashSet < Symbol > ,
1567
+
1566
1568
region_index : usize ,
1567
1569
binder_depth : usize ,
1568
1570
printed_type_count : usize ,
@@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2118
2120
where
2119
2121
T : Print < ' tcx , Self , Output = Self , Error = fmt:: Error > + TypeFoldable < ' tcx > ,
2120
2122
{
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) )
2126
2132
}
2127
2133
}
2128
2134
2135
+ debug ! ( "name_all_regions" ) ;
2136
+
2129
2137
// Replace any anonymous late-bound regions with named
2130
2138
// variants, using new unique identifiers, so that we can
2131
2139
// clearly differentiate between named and unnamed regions in
2132
2140
// the output. We'll probably want to tweak this over time to
2133
2141
// decide just how much information to give.
2134
2142
if self . binder_depth == 0 {
2135
- self . prepare_late_bound_region_info ( value) ;
2143
+ self . prepare_region_info ( value) ;
2136
2144
}
2137
2145
2146
+ debug ! ( "self.used_region_names: {:?}" , & self . used_region_names) ;
2147
+
2138
2148
let mut empty = true ;
2139
2149
let mut start_or_continue = |cx : & mut Self , start : & str , cont : & str | {
2140
2150
let w = if empty {
@@ -2151,13 +2161,24 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2151
2161
2152
2162
define_scoped_cx ! ( self ) ;
2153
2163
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
+
2154
2174
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) ;
2157
2178
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
2161
2182
} ;
2162
2183
2163
2184
// If we want to print verbosely, then print *all* binders, even if they
@@ -2178,6 +2199,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2178
2199
ty:: BrAnon ( _) | ty:: BrEnv => {
2179
2200
start_or_continue ( & mut self , "for<" , ", " ) ;
2180
2201
let name = next_name ( & self ) ;
2202
+ debug ! ( ?name) ;
2181
2203
do_continue ( & mut self , name) ;
2182
2204
ty:: BrNamed ( CRATE_DEF_ID . to_def_id ( ) , name)
2183
2205
}
@@ -2271,29 +2293,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2271
2293
Ok ( inner)
2272
2294
}
2273
2295
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 > )
2275
2297
where
2276
2298
T : TypeVisitable < ' tcx > ,
2277
2299
{
2278
- struct LateBoundRegionNameCollector < ' a , ' tcx > {
2279
- used_region_names : & ' a mut FxHashSet < Symbol > ,
2300
+ struct RegionNameCollector < ' tcx > {
2301
+ used_region_names : FxHashSet < Symbol > ,
2280
2302
type_collector : SsoHashSet < Ty < ' tcx > > ,
2281
2303
}
2282
2304
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 > {
2284
2315
type BreakTy = ( ) ;
2285
2316
2286
2317
fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
2287
2318
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 ( ) {
2295
2324
self . used_region_names . insert ( name) ;
2296
2325
}
2326
+
2297
2327
r. super_visit_with ( self )
2298
2328
}
2299
2329
@@ -2309,12 +2339,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2309
2339
}
2310
2340
}
2311
2341
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 ( ) ;
2317
2343
value. visit_with ( & mut collector) ;
2344
+ self . used_region_names = collector. used_region_names ;
2318
2345
self . region_index = 0 ;
2319
2346
}
2320
2347
}
0 commit comments