@@ -5,10 +5,13 @@ use rustc_index::interval::IntervalSet;
55use rustc_infer:: infer:: canonical:: QueryRegionConstraints ;
66use rustc_middle:: mir:: { BasicBlock , Body , ConstraintCategory , Local , Location } ;
77use rustc_middle:: traits:: query:: DropckOutlivesResult ;
8- use rustc_middle:: ty:: { RegionVid , Ty , TyCtxt , TypeVisitable , TypeVisitableExt } ;
8+ use rustc_middle:: ty:: {
9+ self , RegionVid , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
10+ } ;
911use rustc_span:: DUMMY_SP ;
1012use rustc_trait_selection:: traits:: query:: type_op:: outlives:: DropckOutlives ;
1113use rustc_trait_selection:: traits:: query:: type_op:: { TypeOp , TypeOpOutput } ;
14+ use std:: ops:: ControlFlow ;
1215use std:: rc:: Rc ;
1316
1417use rustc_mir_dataflow:: impls:: MaybeInitializedPlaces ;
@@ -601,34 +604,88 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
601604 values:: location_set_str( elements, live_at. iter( ) ) ,
602605 ) ;
603606
604- let tcx = typeck. tcx ( ) ;
605- let borrowck_context = & mut typeck. borrowck_context ;
606-
607607 // When using `-Zpolonius=next`, we want to record the loans that flow into this value's
608608 // regions as being live at the given `live_at` points: this will be used to compute the
609609 // location where a loan goes out of scope.
610- let num_loans = borrowck_context. borrow_set . len ( ) ;
611- let mut value_loans = HybridBitSet :: new_empty ( num_loans) ;
612-
613- tcx. for_each_free_region ( & value, |live_region| {
614- let live_region_vid = borrowck_context. universal_regions . to_region_vid ( live_region) ;
610+ let num_loans = typeck. borrowck_context . borrow_set . len ( ) ;
611+ let value_loans = & mut HybridBitSet :: new_empty ( num_loans) ;
612+
613+ struct MakeAllRegionsLive < ' a , ' b , ' tcx > {
614+ typeck : & ' b mut TypeChecker < ' a , ' tcx > ,
615+ live_at : & ' b IntervalSet < PointIndex > ,
616+ value_loans : & ' b mut HybridBitSet < BorrowIndex > ,
617+ inflowing_loans : & ' b SparseBitMatrix < RegionVid , BorrowIndex > ,
618+ }
619+ impl < ' tcx > MakeAllRegionsLive < ' _ , ' _ , ' tcx > {
620+ fn make_alias_live ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < !> {
621+ let ty:: Alias ( _kind, alias_ty) = t. kind ( ) else {
622+ bug ! ( ) ;
623+ } ;
624+ let tcx = self . typeck . infcx . tcx ;
625+ let mut outlives_bounds = tcx
626+ . item_bounds ( alias_ty. def_id )
627+ . iter_instantiated ( tcx, alias_ty. args )
628+ . filter_map ( |clause| {
629+ if let Some ( outlives) = clause. as_type_outlives_clause ( )
630+ && outlives. skip_binder ( ) . 0 == t
631+ {
632+ Some ( outlives. skip_binder ( ) . 1 )
633+ } else {
634+ None
635+ }
636+ } ) ;
637+ if let Some ( r) = outlives_bounds. next ( )
638+ && !r. is_late_bound ( )
639+ && outlives_bounds. all ( |other_r| {
640+ other_r == r
641+ } )
642+ {
643+ r. visit_with ( self )
644+ } else {
645+ t. super_visit_with ( self )
646+ }
647+ }
648+ }
649+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for MakeAllRegionsLive < ' _ , ' _ , ' tcx > {
650+ type BreakTy = !;
615651
616- borrowck_context
617- . constraints
618- . liveness_constraints
619- . add_elements ( live_region_vid, live_at) ;
652+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
653+ if r. is_late_bound ( ) {
654+ return ControlFlow :: Continue ( ( ) ) ;
655+ }
656+ let live_region_vid =
657+ self . typeck . borrowck_context . universal_regions . to_region_vid ( r) ;
658+
659+ self . typeck
660+ . borrowck_context
661+ . constraints
662+ . liveness_constraints
663+ . add_elements ( live_region_vid, self . live_at ) ;
664+
665+ // There can only be inflowing loans for this region when we are using
666+ // `-Zpolonius=next`.
667+ if let Some ( inflowing) = self . inflowing_loans . row ( live_region_vid) {
668+ self . value_loans . union ( inflowing) ;
669+ }
670+ ControlFlow :: Continue ( ( ) )
671+ }
620672
621- // There can only be inflowing loans for this region when we are using
622- // `-Zpolonius=next`.
623- if let Some ( inflowing) = inflowing_loans. row ( live_region_vid) {
624- value_loans. union ( inflowing) ;
673+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
674+ if !t. has_free_regions ( ) {
675+ ControlFlow :: Continue ( ( ) )
676+ } else if let ty:: Alias ( ..) = t. kind ( ) {
677+ self . make_alias_live ( t)
678+ } else {
679+ t. super_visit_with ( self )
680+ }
625681 }
626- } ) ;
682+ }
683+ value. visit_with ( & mut MakeAllRegionsLive { typeck, live_at, value_loans, inflowing_loans } ) ;
627684
628685 // Record the loans reaching the value.
629686 if !value_loans. is_empty ( ) {
630687 for point in live_at. iter ( ) {
631- borrowck_context. live_loans . union_row ( point, & value_loans) ;
688+ typeck . borrowck_context . live_loans . union_row ( point, value_loans) ;
632689 }
633690 }
634691 }
0 commit comments