@@ -5,10 +5,13 @@ use rustc_index::interval::IntervalSet;
5
5
use rustc_infer:: infer:: canonical:: QueryRegionConstraints ;
6
6
use rustc_middle:: mir:: { BasicBlock , Body , ConstraintCategory , Local , Location } ;
7
7
use 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
+ } ;
9
11
use rustc_span:: DUMMY_SP ;
10
12
use rustc_trait_selection:: traits:: query:: type_op:: outlives:: DropckOutlives ;
11
13
use rustc_trait_selection:: traits:: query:: type_op:: { TypeOp , TypeOpOutput } ;
14
+ use std:: ops:: ControlFlow ;
12
15
use std:: rc:: Rc ;
13
16
14
17
use rustc_mir_dataflow:: impls:: MaybeInitializedPlaces ;
@@ -601,34 +604,88 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
601
604
values:: location_set_str( elements, live_at. iter( ) ) ,
602
605
) ;
603
606
604
- let tcx = typeck. tcx ( ) ;
605
- let borrowck_context = & mut typeck. borrowck_context ;
606
-
607
607
// When using `-Zpolonius=next`, we want to record the loans that flow into this value's
608
608
// regions as being live at the given `live_at` points: this will be used to compute the
609
609
// 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 = !;
615
651
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
+ }
620
672
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
+ }
625
681
}
626
- } ) ;
682
+ }
683
+ value. visit_with ( & mut MakeAllRegionsLive { typeck, live_at, value_loans, inflowing_loans } ) ;
627
684
628
685
// Record the loans reaching the value.
629
686
if !value_loans. is_empty ( ) {
630
687
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) ;
632
689
}
633
690
}
634
691
}
0 commit comments