@@ -1572,7 +1572,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
1572
1572
in_value : bool ,
1573
1573
pub print_alloc_ids : bool ,
1574
1574
1575
+ // set of all named (non-anonymous) region names
1575
1576
used_region_names : FxHashSet < Symbol > ,
1577
+
1576
1578
region_index : usize ,
1577
1579
binder_depth : usize ,
1578
1580
printed_type_count : usize ,
@@ -2139,23 +2141,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2139
2141
where
2140
2142
T : Print < ' tcx , Self , Output = Self , Error = fmt:: Error > + TypeFoldable < ' tcx > ,
2141
2143
{
2142
- fn name_by_region_index ( index : usize ) -> Symbol {
2143
- match index {
2144
- 0 => Symbol :: intern ( "'r" ) ,
2145
- 1 => Symbol :: intern ( "'s" ) ,
2146
- i => Symbol :: intern ( & format ! ( "'t{}" , i - 2 ) ) ,
2144
+ fn name_by_region_index (
2145
+ index : usize ,
2146
+ available_names : & mut Vec < Symbol > ,
2147
+ num_available : usize ,
2148
+ ) -> Symbol {
2149
+ if let Some ( name) = available_names. pop ( ) {
2150
+ name
2151
+ } else {
2152
+ Symbol :: intern ( & format ! ( "'t{}" , index - num_available) )
2147
2153
}
2148
2154
}
2149
2155
2156
+ debug ! ( "name_all_regions" ) ;
2157
+
2150
2158
// Replace any anonymous late-bound regions with named
2151
2159
// variants, using new unique identifiers, so that we can
2152
2160
// clearly differentiate between named and unnamed regions in
2153
2161
// the output. We'll probably want to tweak this over time to
2154
2162
// decide just how much information to give.
2155
2163
if self . binder_depth == 0 {
2156
- self . prepare_late_bound_region_info ( value) ;
2164
+ self . prepare_region_info ( value) ;
2157
2165
}
2158
2166
2167
+ debug ! ( "self.used_region_names: {:?}" , & self . used_region_names) ;
2168
+
2159
2169
let mut empty = true ;
2160
2170
let mut start_or_continue = |cx : & mut Self , start : & str , cont : & str | {
2161
2171
let w = if empty {
@@ -2172,13 +2182,23 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2172
2182
2173
2183
define_scoped_cx ! ( self ) ;
2174
2184
2185
+ let possible_names = vec ! [ Symbol :: intern( "'t" ) , Symbol :: intern( "'s" ) , Symbol :: intern( "'r" ) ] ;
2186
+
2187
+ let mut available_names = possible_names
2188
+ . into_iter ( )
2189
+ . filter ( |name| !self . used_region_names . contains ( & name) )
2190
+ . collect :: < Vec < _ > > ( ) ;
2191
+ debug ! ( ?available_names) ;
2192
+ let num_available = available_names. len ( ) ;
2193
+
2175
2194
let mut region_index = self . region_index ;
2176
- let mut next_name = |this : & Self | loop {
2177
- let name = name_by_region_index ( region_index) ;
2195
+ let mut next_name = |this : & Self | {
2196
+ let name = name_by_region_index ( region_index, & mut available_names, num_available) ;
2197
+ debug ! ( ?name) ;
2178
2198
region_index += 1 ;
2179
- if ! this. used_region_names . contains ( & name) {
2180
- break name ;
2181
- }
2199
+ assert ! ( ! this. used_region_names. contains( & name) ) ;
2200
+
2201
+ name
2182
2202
} ;
2183
2203
2184
2204
// If we want to print verbosely, then print *all* binders, even if they
@@ -2199,6 +2219,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2199
2219
ty:: BrAnon ( _) | ty:: BrEnv => {
2200
2220
start_or_continue ( & mut self , "for<" , ", " ) ;
2201
2221
let name = next_name ( & self ) ;
2222
+ debug ! ( ?name) ;
2202
2223
do_continue ( & mut self , name) ;
2203
2224
ty:: BrNamed ( CRATE_DEF_ID . to_def_id ( ) , name)
2204
2225
}
@@ -2292,29 +2313,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2292
2313
Ok ( inner)
2293
2314
}
2294
2315
2295
- fn prepare_late_bound_region_info < T > ( & mut self , value : & ty:: Binder < ' tcx , T > )
2316
+ fn prepare_region_info < T > ( & mut self , value : & ty:: Binder < ' tcx , T > )
2296
2317
where
2297
2318
T : TypeVisitable < ' tcx > ,
2298
2319
{
2299
- struct LateBoundRegionNameCollector < ' a , ' tcx > {
2300
- used_region_names : & ' a mut FxHashSet < Symbol > ,
2320
+ struct RegionNameCollector < ' tcx > {
2321
+ used_region_names : FxHashSet < Symbol > ,
2301
2322
type_collector : SsoHashSet < Ty < ' tcx > > ,
2302
2323
}
2303
2324
2304
- impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for LateBoundRegionNameCollector < ' _ , ' tcx > {
2325
+ impl < ' tcx > RegionNameCollector < ' tcx > {
2326
+ fn new ( ) -> Self {
2327
+ RegionNameCollector {
2328
+ used_region_names : Default :: default ( ) ,
2329
+ type_collector : SsoHashSet :: new ( ) ,
2330
+ }
2331
+ }
2332
+ }
2333
+
2334
+ impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for RegionNameCollector < ' tcx > {
2305
2335
type BreakTy = ( ) ;
2306
2336
2307
2337
fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
2308
2338
trace ! ( "address: {:p}" , r. 0.0 ) ;
2309
- if let ty:: ReLateBound ( _, ty:: BoundRegion { kind : ty:: BrNamed ( _, name) , .. } ) = * r {
2310
- self . used_region_names . insert ( name) ;
2311
- } else if let ty:: RePlaceholder ( ty:: PlaceholderRegion {
2312
- name : ty:: BrNamed ( _, name) ,
2313
- ..
2314
- } ) = * r
2315
- {
2339
+
2340
+ // Collect all named lifetimes. These allow us to prevent duplication
2341
+ // of already existing lifetime names when introducing names for
2342
+ // anonymous late-bound regions.
2343
+ if let Some ( name) = r. get_name ( ) {
2316
2344
self . used_region_names . insert ( name) ;
2317
2345
}
2346
+
2318
2347
r. super_visit_with ( self )
2319
2348
}
2320
2349
@@ -2330,12 +2359,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
2330
2359
}
2331
2360
}
2332
2361
2333
- self . used_region_names . clear ( ) ;
2334
- let mut collector = LateBoundRegionNameCollector {
2335
- used_region_names : & mut self . used_region_names ,
2336
- type_collector : SsoHashSet :: new ( ) ,
2337
- } ;
2362
+ let mut collector = RegionNameCollector :: new ( ) ;
2338
2363
value. visit_with ( & mut collector) ;
2364
+ self . used_region_names = collector. used_region_names ;
2339
2365
self . region_index = 0 ;
2340
2366
}
2341
2367
}
0 commit comments