@@ -7,7 +7,7 @@ use super::{
7
7
InferCtxtUndoLogs , MiscVariable , RegionVariableOrigin , Rollback , Snapshot , SubregionOrigin ,
8
8
} ;
9
9
10
- use rustc_data_structures:: fx:: FxHashMap ;
10
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
11
11
use rustc_data_structures:: intern:: Interned ;
12
12
use rustc_data_structures:: sync:: Lrc ;
13
13
use rustc_data_structures:: undo_log:: UndoLogs ;
@@ -104,6 +104,26 @@ pub struct RegionConstraintData<'tcx> {
104
104
/// An example is a `A <= B` where neither `A` nor `B` are
105
105
/// inference variables.
106
106
pub verifys : Vec < Verify < ' tcx > > ,
107
+
108
+ /// A "given" is a relationship that is known to hold. In
109
+ /// particular, we often know from closure fn signatures that a
110
+ /// particular free region must be a subregion of a region
111
+ /// variable:
112
+ ///
113
+ /// foo.iter().filter(<'a> |x: &'a &'b T| ...)
114
+ ///
115
+ /// In situations like this, `'b` is in fact a region variable
116
+ /// introduced by the call to `iter()`, and `'a` is a bound region
117
+ /// on the closure (as indicated by the `<'a>` prefix). If we are
118
+ /// naive, we wind up inferring that `'b` must be `'static`,
119
+ /// because we require that it be greater than `'a` and we do not
120
+ /// know what `'a` is precisely.
121
+ ///
122
+ /// This hashmap is used to avoid that naive scenario. Basically
123
+ /// we record the fact that `'a <= 'b` is implied by the fn
124
+ /// signature, and then ignore the constraint when solving
125
+ /// equations. This is a bit of a hack but seems to work.
126
+ pub givens : FxIndexSet < ( Region < ' tcx > , ty:: RegionVid ) > ,
107
127
}
108
128
109
129
/// Represents a constraint that influences the inference process.
@@ -277,6 +297,9 @@ pub(crate) enum UndoLog<'tcx> {
277
297
/// We added the given `verify`.
278
298
AddVerify ( usize ) ,
279
299
300
+ /// We added the given `given`.
301
+ AddGiven ( Region < ' tcx > , ty:: RegionVid ) ,
302
+
280
303
/// We added a GLB/LUB "combination variable".
281
304
AddCombination ( CombineMapType , TwoRegions < ' tcx > ) ,
282
305
}
@@ -325,6 +348,9 @@ impl<'tcx> RegionConstraintStorage<'tcx> {
325
348
self . data . verifys . pop ( ) ;
326
349
assert_eq ! ( self . data. verifys. len( ) , index) ;
327
350
}
351
+ AddGiven ( sub, sup) => {
352
+ self . data . givens . remove ( & ( sub, sup) ) ;
353
+ }
328
354
AddCombination ( Glb , ref regions) => {
329
355
self . glbs . remove ( regions) ;
330
356
}
@@ -466,6 +492,15 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
466
492
self . undo_log . push ( AddVerify ( index) ) ;
467
493
}
468
494
495
+ pub ( super ) fn add_given ( & mut self , sub : Region < ' tcx > , sup : ty:: RegionVid ) {
496
+ // cannot add givens once regions are resolved
497
+ if self . data . givens . insert ( ( sub, sup) ) {
498
+ debug ! ( "add_given({:?} <= {:?})" , sub, sup) ;
499
+
500
+ self . undo_log . push ( AddGiven ( sub, sup) ) ;
501
+ }
502
+ }
503
+
469
504
pub ( super ) fn make_eqregion (
470
505
& mut self ,
471
506
origin : SubregionOrigin < ' tcx > ,
@@ -769,8 +804,11 @@ impl<'tcx> RegionConstraintData<'tcx> {
769
804
/// Returns `true` if this region constraint data contains no constraints, and `false`
770
805
/// otherwise.
771
806
pub fn is_empty ( & self ) -> bool {
772
- let RegionConstraintData { constraints, member_constraints, verifys } = self ;
773
- constraints. is_empty ( ) && member_constraints. is_empty ( ) && verifys. is_empty ( )
807
+ let RegionConstraintData { constraints, member_constraints, verifys, givens } = self ;
808
+ constraints. is_empty ( )
809
+ && member_constraints. is_empty ( )
810
+ && verifys. is_empty ( )
811
+ && givens. is_empty ( )
774
812
}
775
813
}
776
814
0 commit comments