@@ -243,11 +243,20 @@ impl<'tcx> CtxtInterners<'tcx> {
243
243
}
244
244
}
245
245
246
+ // For these preinterned values, an alternative would be to have
247
+ // variable-length vectors that grow as needed. But that turned out to be
248
+ // slightly more complex and no faster.
249
+
246
250
const NUM_PREINTERNED_TY_VARS : u32 = 100 ;
247
251
const NUM_PREINTERNED_FRESH_TYS : u32 = 20 ;
248
252
const NUM_PREINTERNED_FRESH_INT_TYS : u32 = 3 ;
249
253
const NUM_PREINTERNED_FRESH_FLOAT_TYS : u32 = 3 ;
250
254
255
+ // This number may seem high, but it is reached in all but the smallest crates.
256
+ const NUM_PREINTERNED_RE_VARS : u32 = 500 ;
257
+ const NUM_PREINTERNED_RE_LATE_BOUNDS_I : u32 = 2 ;
258
+ const NUM_PREINTERNED_RE_LATE_BOUNDS_V : u32 = 20 ;
259
+
251
260
pub struct CommonTypes < ' tcx > {
252
261
pub unit : Ty < ' tcx > ,
253
262
pub bool : Ty < ' tcx > ,
@@ -295,6 +304,14 @@ pub struct CommonLifetimes<'tcx> {
295
304
296
305
/// Erased region, used outside of type inference.
297
306
pub re_erased : Region < ' tcx > ,
307
+
308
+ /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
309
+ pub re_vars : Vec < Region < ' tcx > > ,
310
+
311
+ /// Pre-interned values of the form:
312
+ /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })
313
+ /// for small values of `i` and `v`.
314
+ pub re_late_bounds : Vec < Vec < Region < ' tcx > > > ,
298
315
}
299
316
300
317
pub struct CommonConsts < ' tcx > {
@@ -358,7 +375,31 @@ impl<'tcx> CommonLifetimes<'tcx> {
358
375
) )
359
376
} ;
360
377
361
- CommonLifetimes { re_static : mk ( ty:: ReStatic ) , re_erased : mk ( ty:: ReErased ) }
378
+ let re_vars =
379
+ ( 0 ..NUM_PREINTERNED_RE_VARS ) . map ( |n| mk ( ty:: ReVar ( ty:: RegionVid :: from ( n) ) ) ) . collect ( ) ;
380
+
381
+ let re_late_bounds = ( 0 ..NUM_PREINTERNED_RE_LATE_BOUNDS_I )
382
+ . map ( |i| {
383
+ ( 0 ..NUM_PREINTERNED_RE_LATE_BOUNDS_V )
384
+ . map ( |v| {
385
+ mk ( ty:: ReLateBound (
386
+ ty:: DebruijnIndex :: from ( i) ,
387
+ ty:: BoundRegion {
388
+ var : ty:: BoundVar :: from ( v) ,
389
+ kind : ty:: BrAnon ( v, None ) ,
390
+ } ,
391
+ ) )
392
+ } )
393
+ . collect ( )
394
+ } )
395
+ . collect ( ) ;
396
+
397
+ CommonLifetimes {
398
+ re_static : mk ( ty:: ReStatic ) ,
399
+ re_erased : mk ( ty:: ReErased ) ,
400
+ re_vars,
401
+ re_late_bounds,
402
+ }
362
403
}
363
404
}
364
405
@@ -697,15 +738,15 @@ impl<'tcx> TyCtxt<'tcx> {
697
738
698
739
/// Constructs a `RegionKind::ReError` lifetime.
699
740
#[ track_caller]
700
- pub fn re_error ( self , reported : ErrorGuaranteed ) -> Region < ' tcx > {
701
- self . mk_region ( ty:: ReError ( reported) )
741
+ pub fn mk_re_error ( self , reported : ErrorGuaranteed ) -> Region < ' tcx > {
742
+ self . intern_region ( ty:: ReError ( reported) )
702
743
}
703
744
704
745
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
705
746
/// gets used.
706
747
#[ track_caller]
707
- pub fn re_error_misc ( self ) -> Region < ' tcx > {
708
- self . re_error_with_message (
748
+ pub fn mk_re_error_misc ( self ) -> Region < ' tcx > {
749
+ self . mk_re_error_with_message (
709
750
DUMMY_SP ,
710
751
"RegionKind::ReError constructed but no error reported" ,
711
752
)
@@ -714,9 +755,9 @@ impl<'tcx> TyCtxt<'tcx> {
714
755
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
715
756
/// `msg` to ensure it gets used.
716
757
#[ track_caller]
717
- pub fn re_error_with_message < S : Into < MultiSpan > > ( self , span : S , msg : & str ) -> Region < ' tcx > {
758
+ pub fn mk_re_error_with_message < S : Into < MultiSpan > > ( self , span : S , msg : & str ) -> Region < ' tcx > {
718
759
let reported = self . sess . delay_span_bug ( span, msg) ;
719
- self . re_error ( reported)
760
+ self . mk_re_error ( reported)
720
761
}
721
762
722
763
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
@@ -1517,7 +1558,7 @@ macro_rules! direct_interners {
1517
1558
}
1518
1559
1519
1560
direct_interners ! {
1520
- region: mk_region ( RegionKind <' tcx>) : Region -> Region <' tcx>,
1561
+ region: intern_region ( RegionKind <' tcx>) : Region -> Region <' tcx>,
1521
1562
const_: mk_const_internal( ConstData <' tcx>) : Const -> Const <' tcx>,
1522
1563
const_allocation: intern_const_alloc( Allocation ) : ConstAllocation -> ConstAllocation <' tcx>,
1523
1564
layout: intern_layout( LayoutS ) : Layout -> Layout <' tcx>,
@@ -1631,13 +1672,6 @@ impl<'tcx> TyCtxt<'tcx> {
1631
1672
} )
1632
1673
}
1633
1674
1634
- /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
1635
- /// `*r == kind`.
1636
- #[ inline]
1637
- pub fn reuse_or_mk_region ( self , r : Region < ' tcx > , kind : RegionKind < ' tcx > ) -> Region < ' tcx > {
1638
- if * r == kind { r } else { self . mk_region ( kind) }
1639
- }
1640
-
1641
1675
// Avoid this in favour of more specific `mk_*` methods, where possible.
1642
1676
#[ allow( rustc:: usage_of_ty_tykind) ]
1643
1677
#[ inline]
@@ -1966,7 +2000,7 @@ impl<'tcx> TyCtxt<'tcx> {
1966
2000
pub fn mk_param_from_def ( self , param : & ty:: GenericParamDef ) -> GenericArg < ' tcx > {
1967
2001
match param. kind {
1968
2002
GenericParamDefKind :: Lifetime => {
1969
- self . mk_region ( ty :: ReEarlyBound ( param. to_early_bound_region_data ( ) ) ) . into ( )
2003
+ self . mk_re_early_bound ( param. to_early_bound_region_data ( ) ) . into ( )
1970
2004
}
1971
2005
GenericParamDefKind :: Type { .. } => self . mk_ty_param ( param. index , param. name ) . into ( ) ,
1972
2006
GenericParamDefKind :: Const { .. } => self
@@ -1998,6 +2032,66 @@ impl<'tcx> TyCtxt<'tcx> {
1998
2032
self . mk_alias ( ty:: Opaque , self . mk_alias_ty ( def_id, substs) )
1999
2033
}
2000
2034
2035
+ #[ inline]
2036
+ pub fn mk_re_early_bound ( self , early_bound_region : ty:: EarlyBoundRegion ) -> Region < ' tcx > {
2037
+ self . intern_region ( ty:: ReEarlyBound ( early_bound_region) )
2038
+ }
2039
+
2040
+ #[ inline]
2041
+ pub fn mk_re_late_bound (
2042
+ self ,
2043
+ debruijn : ty:: DebruijnIndex ,
2044
+ bound_region : ty:: BoundRegion ,
2045
+ ) -> Region < ' tcx > {
2046
+ // Use a pre-interned one when possible.
2047
+ if let ty:: BoundRegion { var, kind : ty:: BrAnon ( v, None ) } = bound_region
2048
+ && var. as_u32 ( ) == v
2049
+ && let Some ( inner) = self . lifetimes . re_late_bounds . get ( debruijn. as_usize ( ) )
2050
+ && let Some ( re) = inner. get ( v as usize ) . copied ( )
2051
+ {
2052
+ re
2053
+ } else {
2054
+ self . intern_region ( ty:: ReLateBound ( debruijn, bound_region) )
2055
+ }
2056
+ }
2057
+
2058
+ #[ inline]
2059
+ pub fn mk_re_free ( self , scope : DefId , bound_region : ty:: BoundRegionKind ) -> Region < ' tcx > {
2060
+ self . intern_region ( ty:: ReFree ( ty:: FreeRegion { scope, bound_region } ) )
2061
+ }
2062
+
2063
+ #[ inline]
2064
+ pub fn mk_re_var ( self , v : ty:: RegionVid ) -> Region < ' tcx > {
2065
+ // Use a pre-interned one when possible.
2066
+ self . lifetimes
2067
+ . re_vars
2068
+ . get ( v. as_usize ( ) )
2069
+ . copied ( )
2070
+ . unwrap_or_else ( || self . intern_region ( ty:: ReVar ( v) ) )
2071
+ }
2072
+
2073
+ #[ inline]
2074
+ pub fn mk_re_placeholder ( self , placeholder : ty:: PlaceholderRegion ) -> Region < ' tcx > {
2075
+ self . intern_region ( ty:: RePlaceholder ( placeholder) )
2076
+ }
2077
+
2078
+ // Avoid this in favour of more specific `mk_re_*` methods, where possible,
2079
+ // to avoid the cost of the `match`.
2080
+ pub fn mk_region ( self , kind : ty:: RegionKind < ' tcx > ) -> Region < ' tcx > {
2081
+ match kind {
2082
+ ty:: ReEarlyBound ( region) => self . mk_re_early_bound ( region) ,
2083
+ ty:: ReLateBound ( debruijn, region) => self . mk_re_late_bound ( debruijn, region) ,
2084
+ ty:: ReFree ( ty:: FreeRegion { scope, bound_region } ) => {
2085
+ self . mk_re_free ( scope, bound_region)
2086
+ }
2087
+ ty:: ReStatic => self . lifetimes . re_static ,
2088
+ ty:: ReVar ( vid) => self . mk_re_var ( vid) ,
2089
+ ty:: RePlaceholder ( region) => self . mk_re_placeholder ( region) ,
2090
+ ty:: ReErased => self . lifetimes . re_erased ,
2091
+ ty:: ReError ( reported) => self . mk_re_error ( reported) ,
2092
+ }
2093
+ }
2094
+
2001
2095
pub fn mk_place_field ( self , place : Place < ' tcx > , f : Field , ty : Ty < ' tcx > ) -> Place < ' tcx > {
2002
2096
self . mk_place_elem ( place, PlaceElem :: Field ( f, ty) )
2003
2097
}
0 commit comments