@@ -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