@@ -645,6 +645,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
645645 }
646646 }
647647
648+ /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot
649+ /// prove to be satisfied. If this is a closure, we will attempt to
650+ /// "promote" this type-test into our `ClosureRegionRequirements` and
651+ /// hence pass it up the creator. To do this, we have to phrase the
652+ /// type-test in terms of external free regions, as local free
653+ /// regions are not nameable by the closure's creator.
654+ ///
655+ /// Promotion works as follows: we first check that the type `T`
656+ /// contains only regions that the creator knows about. If this is
657+ /// true, then -- as a consequence -- we know that all regions in
658+ /// the type `T` are free regions that outlive the closure body. If
659+ /// false, then promotion fails.
660+ ///
661+ /// Once we've promoted T, we have to "promote" `'X` to some region
662+ /// that is "external" to the closure. Generally speaking, a region
663+ /// may be the union of some points in the closure body as well as
664+ /// various free lifetimes. We can ignore the points in the closure
665+ /// body: if the type T can be expressed in terms of external regions,
666+ /// we know it outlives the points in the closure body. That
667+ /// just leaves the free regions.
668+ ///
669+ /// The idea then is to lower the `T: 'X` constraint into multiple
670+ /// bounds -- e.g., if `'X` is the union of two free lifetimes,
671+ /// `'1` and `'2`, then we would create `T: '1` and `T: '2`.
648672 fn try_promote_type_test < ' gcx > (
649673 & self ,
650674 infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
@@ -661,28 +685,33 @@ impl<'tcx> RegionInferenceContext<'tcx> {
661685 test : _,
662686 } = type_test;
663687
688+
664689 let generic_ty = generic_kind. to_ty ( tcx) ;
665690 let subject = match self . try_promote_type_test_subject ( infcx, generic_ty) {
666691 Some ( s) => s,
667692 None => return false ,
668693 } ;
669694
670- // Find some bounding subject-region R+ that is a super-region
671- // of the existing subject-region R. This should be a non-local, universal
672- // region, which ensures it can be encoded in a `ClosureOutlivesRequirement`.
673- let lower_bound_plus = self . non_local_universal_upper_bound ( * lower_bound) ;
674- assert ! ( self . universal_regions. is_universal_region( lower_bound_plus) ) ;
675- assert ! (
676- !self
695+ // For each region outlived by lower_bound find a non-local,
696+ // universal region (it may be the same region) and add it to
697+ // `ClosureOutlivesRequirement`.
698+ let r_scc = self . constraint_sccs . scc ( * lower_bound) ;
699+ for ur in self . scc_values . universal_regions_outlived_by ( r_scc) {
700+ let non_local_ub = self . universal_region_relations . non_local_upper_bound ( ur) ;
701+
702+ assert ! ( self . universal_regions. is_universal_region( non_local_ub) ) ;
703+ assert ! (
704+ !self
677705 . universal_regions
678- . is_local_free_region( lower_bound_plus )
679- ) ;
706+ . is_local_free_region( non_local_ub )
707+ ) ;
680708
681- propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
682- subject,
683- outlived_free_region : lower_bound_plus,
684- blame_span : locations. span ( mir) ,
685- } ) ;
709+ propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
710+ subject,
711+ outlived_free_region : non_local_ub,
712+ blame_span : locations. span ( mir) ,
713+ } ) ;
714+ }
686715 true
687716 }
688717
0 commit comments