@@ -712,21 +712,65 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
712
712
traits:: ObligationCause :: misc ( span, self . body_id )
713
713
}
714
714
715
- #[ inline( never) ]
716
- fn fully_perform_op < OP , R > (
715
+ /// Given some operation `op` that manipulates types, proves
716
+ /// predicates, or otherwise uses the inference context, executes
717
+ /// `op` and then executes all the further obligations that `op`
718
+ /// returns. This will yield a set of outlives constraints amongst
719
+ /// regions which are extracted and stored as having occured at
720
+ /// `locations`.
721
+ ///
722
+ /// **Any `rustc::infer` operations that might generate region
723
+ /// constraints should occur within this method so that those
724
+ /// constraints can be properly localized!**
725
+ fn fully_perform_op < R > (
717
726
& mut self ,
718
727
locations : Locations ,
719
728
describe_op : impl Fn ( ) -> String ,
720
- op : OP ,
721
- ) -> Result < R , TypeError < ' tcx > >
722
- where
723
- OP : FnOnce ( & mut Self ) -> InferResult < ' tcx , R > ,
724
- {
729
+ op : impl FnOnce ( & mut Self ) -> InferResult < ' tcx , R > ,
730
+ ) -> Result < R , TypeError < ' tcx > > {
731
+ let ( r, opt_data) = self . fully_perform_op_and_get_region_constraint_data (
732
+ || format ! ( "{} at {:?}" , describe_op( ) , locations) ,
733
+ op,
734
+ ) ?;
735
+
736
+ if let Some ( data) = opt_data {
737
+ self . push_region_constraints ( locations, data) ;
738
+ }
739
+
740
+ Ok ( r)
741
+ }
742
+
743
+ fn push_region_constraints (
744
+ & mut self ,
745
+ locations : Locations ,
746
+ data : Rc < RegionConstraintData < ' tcx > > ,
747
+ ) {
748
+ debug ! (
749
+ "push_region_constraints: constraints generated at {:?} are {:#?}" ,
750
+ locations, data
751
+ ) ;
752
+
753
+ self . constraints
754
+ . outlives_sets
755
+ . push ( OutlivesSet { locations, data } ) ;
756
+ }
757
+
758
+ /// Helper for `fully_perform_op`, but also used on its own
759
+ /// sometimes to enable better caching: executes `op` fully (along
760
+ /// with resulting obligations) and returns the full set of region
761
+ /// obligations. If the same `op` were to be performed at some
762
+ /// other location, then the same set of region obligations would
763
+ /// be generated there, so this can be useful for caching.
764
+ #[ inline( never) ]
765
+ fn fully_perform_op_and_get_region_constraint_data < R > (
766
+ & mut self ,
767
+ describe_op : impl Fn ( ) -> String ,
768
+ op : impl FnOnce ( & mut Self ) -> InferResult < ' tcx , R > ,
769
+ ) -> Result < ( R , Option < Rc < RegionConstraintData < ' tcx > > > ) , TypeError < ' tcx > > {
725
770
if cfg ! ( debug_assertions) {
726
771
info ! (
727
- "fully_perform_op(describe_op= {}) at {:?} " ,
772
+ "fully_perform_op_and_get_region_constraint_data( {})" ,
728
773
describe_op( ) ,
729
- locations
730
774
) ;
731
775
}
732
776
@@ -745,18 +789,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
745
789
) ;
746
790
747
791
let data = self . infcx . take_and_reset_region_constraints ( ) ;
748
- if !data. is_empty ( ) {
749
- debug ! (
750
- "fully_perform_op: constraints generated at {:?} are {:#?}" ,
751
- locations, data
752
- ) ;
753
- let data = Rc :: new ( data) ;
754
- self . constraints
755
- . outlives_sets
756
- . push ( OutlivesSet { locations, data } ) ;
792
+ if data. is_empty ( ) {
793
+ Ok ( ( value, None ) )
794
+ } else {
795
+ Ok ( ( value, Some ( Rc :: new ( data) ) ) )
757
796
}
758
-
759
- Ok ( value)
760
797
}
761
798
762
799
#[ inline( never) ]
0 commit comments