@@ -7,7 +7,7 @@ use super::{
77 InferCtxtUndoLogs , MiscVariable , RegionVariableOrigin , Rollback , Snapshot , SubregionOrigin ,
88} ;
99
10- use rustc_data_structures:: fx:: FxHashMap ;
10+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
1111use rustc_data_structures:: intern:: Interned ;
1212use rustc_data_structures:: sync:: Lrc ;
1313use rustc_data_structures:: undo_log:: UndoLogs ;
@@ -104,6 +104,26 @@ pub struct RegionConstraintData<'tcx> {
104104 /// An example is a `A <= B` where neither `A` nor `B` are
105105 /// inference variables.
106106 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 ) > ,
107127}
108128
109129/// Represents a constraint that influences the inference process.
@@ -277,6 +297,9 @@ pub(crate) enum UndoLog<'tcx> {
277297 /// We added the given `verify`.
278298 AddVerify ( usize ) ,
279299
300+ /// We added the given `given`.
301+ AddGiven ( Region < ' tcx > , ty:: RegionVid ) ,
302+
280303 /// We added a GLB/LUB "combination variable".
281304 AddCombination ( CombineMapType , TwoRegions < ' tcx > ) ,
282305}
@@ -325,6 +348,9 @@ impl<'tcx> RegionConstraintStorage<'tcx> {
325348 self . data . verifys . pop ( ) ;
326349 assert_eq ! ( self . data. verifys. len( ) , index) ;
327350 }
351+ AddGiven ( sub, sup) => {
352+ self . data . givens . remove ( & ( sub, sup) ) ;
353+ }
328354 AddCombination ( Glb , ref regions) => {
329355 self . glbs . remove ( regions) ;
330356 }
@@ -466,6 +492,15 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
466492 self . undo_log . push ( AddVerify ( index) ) ;
467493 }
468494
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+
469504 pub ( super ) fn make_eqregion (
470505 & mut self ,
471506 origin : SubregionOrigin < ' tcx > ,
@@ -769,8 +804,11 @@ impl<'tcx> RegionConstraintData<'tcx> {
769804 /// Returns `true` if this region constraint data contains no constraints, and `false`
770805 /// otherwise.
771806 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 ( )
774812 }
775813}
776814
0 commit comments