11use rustc_data_structures:: fx:: FxIndexSet ;
22use rustc_data_structures:: transitive_relation:: TransitiveRelationBuilder ;
33use rustc_middle:: { bug, ty} ;
4- use tracing:: debug;
54
6- use super :: explicit_outlives_bounds;
75use crate :: infer:: GenericKind ;
86use crate :: infer:: free_regions:: FreeRegionMap ;
9- use crate :: traits:: query:: OutlivesBound ;
107
118/// The `OutlivesEnvironment` collects information about what outlives
129/// what in a given type-checking setting. For example, if we have a
@@ -31,26 +28,7 @@ use crate::traits::query::OutlivesBound;
3128pub struct OutlivesEnvironment < ' tcx > {
3229 pub param_env : ty:: ParamEnv < ' tcx > ,
3330 free_region_map : FreeRegionMap < ' tcx > ,
34-
35- // Contains the implied region bounds in scope for our current body.
36- //
37- // Example:
38- //
39- // ```
40- // fn foo<'a, 'b, T>(x: &'a T, y: &'b ()) {
41- // bar(x, y, |y: &'b T| { .. } // body B1)
42- // } // body B0
43- // ```
44- //
45- // Here, when checking the body B0, the list would be `[T: 'a]`, because we
46- // infer that `T` must outlive `'a` from the implied bounds on the
47- // fn declaration.
48- //
49- // For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we
50- // also can see that -- within the closure body! -- `T` must
51- // outlive `'b`. This is not necessarily true outside the closure
52- // body, since the closure may never be called.
53- region_bound_pairs : RegionBoundPairs < ' tcx > ,
31+ known_type_outlives : Vec < ty:: PolyTypeOutlivesPredicate < ' tcx > > ,
5432}
5533
5634/// "Region-bound pairs" tracks outlives relations that are known to
@@ -59,45 +37,54 @@ pub struct OutlivesEnvironment<'tcx> {
5937pub type RegionBoundPairs < ' tcx > = FxIndexSet < ty:: OutlivesPredicate < ' tcx , GenericKind < ' tcx > > > ;
6038
6139impl < ' tcx > OutlivesEnvironment < ' tcx > {
62- /// Create a new `OutlivesEnvironment` with extra outlives bounds.
63- pub fn with_bounds (
40+ /// Create a new `OutlivesEnvironment` from normalized outlives bounds.
41+ pub fn from_normalized_bounds (
6442 param_env : ty:: ParamEnv < ' tcx > ,
65- extra_bounds : impl IntoIterator < Item = OutlivesBound < ' tcx > > ,
43+ bounds : impl IntoIterator <
44+ Item = ty:: Binder < ' tcx , ty:: OutlivesPredicate < ' tcx , ty:: GenericArg < ' tcx > > > ,
45+ > ,
6646 ) -> Self {
47+ let mut known_type_outlives = vec ! [ ] ;
6748 let mut region_relation = TransitiveRelationBuilder :: default ( ) ;
68- let mut region_bound_pairs = RegionBoundPairs :: default ( ) ;
6949
7050 // Record relationships such as `T:'x` that don't go into the
7151 // free-region-map but which we use here.
72- for outlives_bound in explicit_outlives_bounds ( param_env) . chain ( extra_bounds) {
73- debug ! ( "add_outlives_bounds: outlives_bound={:?}" , outlives_bound) ;
74- match outlives_bound {
75- OutlivesBound :: RegionSubParam ( r_a, param_b) => {
76- region_bound_pairs
77- . insert ( ty:: OutlivesPredicate ( GenericKind :: Param ( param_b) , r_a) ) ;
52+ for bound in bounds {
53+ let ty:: OutlivesPredicate ( arg_b, r_a) = bound. skip_binder ( ) ;
54+ match arg_b. unpack ( ) {
55+ ty:: GenericArgKind :: Lifetime ( r_b) => {
56+ match ( * r_a, * r_b) {
57+ (
58+ ty:: ReStatic | ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) ,
59+ ty:: ReStatic | ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) ,
60+ ) => region_relation. add ( r_a, r_b) ,
61+ // Do nothing for higher-ranked region predicates.
62+ (
63+ ty:: ReBound ( ..) ,
64+ ty:: ReStatic | ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) ,
65+ )
66+ | (
67+ ty:: ReStatic | ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) ,
68+ ty:: ReBound ( ..) ,
69+ ) => { }
70+ ( ty:: ReError ( _) , _) | ( _, ty:: ReError ( _) ) => { }
71+ // FIXME(#109628): We shouldn't have existential variables in implied bounds.
72+ // Panic here once the linked issue is resolved!
73+ ( ty:: ReVar ( _) , _) | ( _, ty:: ReVar ( _) ) => { }
74+ _ => bug ! ( "add_outlives_bounds: unexpected regions: ({r_a:?}, {r_b:?})" ) ,
75+ }
7876 }
79- OutlivesBound :: RegionSubAlias ( r_a, alias_b) => {
80- region_bound_pairs
81- . insert ( ty:: OutlivesPredicate ( GenericKind :: Alias ( alias_b) , r_a) ) ;
77+ ty:: GenericArgKind :: Type ( ty_b) => {
78+ known_type_outlives. push ( bound. rebind ( ty:: OutlivesPredicate ( ty_b, r_a) ) ) ;
8279 }
83- OutlivesBound :: RegionSubRegion ( r_a, r_b) => match ( * r_a, * r_b) {
84- (
85- ty:: ReStatic | ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) ,
86- ty:: ReStatic | ty:: ReEarlyParam ( _) | ty:: ReLateParam ( _) ,
87- ) => region_relation. add ( r_a, r_b) ,
88- ( ty:: ReError ( _) , _) | ( _, ty:: ReError ( _) ) => { }
89- // FIXME(#109628): We shouldn't have existential variables in implied bounds.
90- // Panic here once the linked issue is resolved!
91- ( ty:: ReVar ( _) , _) | ( _, ty:: ReVar ( _) ) => { }
92- _ => bug ! ( "add_outlives_bounds: unexpected regions: ({r_a:?}, {r_b:?})" ) ,
93- } ,
80+ ty:: GenericArgKind :: Const ( _) => unreachable ! ( ) ,
9481 }
9582 }
9683
9784 OutlivesEnvironment {
9885 param_env,
86+ known_type_outlives,
9987 free_region_map : FreeRegionMap { relation : region_relation. freeze ( ) } ,
100- region_bound_pairs,
10188 }
10289 }
10390
@@ -107,7 +94,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
10794 }
10895
10996 /// Borrows current `region_bound_pairs`.
110- pub fn region_bound_pairs ( & self ) -> & RegionBoundPairs < ' tcx > {
111- & self . region_bound_pairs
97+ pub fn known_type_outlives ( & self ) -> & [ ty :: PolyTypeOutlivesPredicate < ' tcx > ] {
98+ & self . known_type_outlives
11299 }
113100}
0 commit comments