@@ -712,21 +712,65 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
712712 traits:: ObligationCause :: misc ( span, self . body_id )
713713 }
714714
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 > (
717726 & mut self ,
718727 locations : Locations ,
719728 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 > > {
725770 if cfg ! ( debug_assertions) {
726771 info ! (
727- "fully_perform_op(describe_op= {}) at {:?} " ,
772+ "fully_perform_op_and_get_region_constraint_data( {})" ,
728773 describe_op( ) ,
729- locations
730774 ) ;
731775 }
732776
@@ -745,18 +789,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
745789 ) ;
746790
747791 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) ) ) )
757796 }
758-
759- Ok ( value)
760797 }
761798
762799 #[ inline( never) ]
0 commit comments