@@ -645,6 +645,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
645
645
}
646
646
}
647
647
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`.
648
672
fn try_promote_type_test < ' gcx > (
649
673
& self ,
650
674
infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
@@ -661,28 +685,33 @@ impl<'tcx> RegionInferenceContext<'tcx> {
661
685
test : _,
662
686
} = type_test;
663
687
688
+
664
689
let generic_ty = generic_kind. to_ty ( tcx) ;
665
690
let subject = match self . try_promote_type_test_subject ( infcx, generic_ty) {
666
691
Some ( s) => s,
667
692
None => return false ,
668
693
} ;
669
694
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
677
705
. universal_regions
678
- . is_local_free_region( lower_bound_plus )
679
- ) ;
706
+ . is_local_free_region( non_local_ub )
707
+ ) ;
680
708
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
+ }
686
715
true
687
716
}
688
717
0 commit comments