rustc_borrowck/polonius/
liveness.rs1use rustc_index::IndexVec;
2use rustc_index::interval::{IntervalSet, SparseIntervalMatrix};
3use rustc_middle::mir::Local;
4use rustc_middle::ty::{GenericArg, RegionVid, Ty, TyCtxt};
5use rustc_mir_dataflow::points::PointIndex;
6
7use crate::polonius::{ConstraintDirection, LiveRegionVariances};
8use crate::region_infer::values::LivenessValues;
9use crate::type_check::liveness::LivenessComputation;
10use crate::universal_regions::UniversalRegions;
11
12pub(super) trait LivenessSource {
14 fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>;
15}
16
17pub(super) struct RegionLiveness<'a> {
19 pub(super) direction: ConstraintDirection,
20 live_points: Option<&'a IntervalSet<PointIndex>>,
21}
22
23impl<'a> RegionLiveness<'a> {
24 #[inline]
25 pub(super) fn new<'tcx>(
26 region: RegionVid,
27 live_region_variances: &LiveRegionVariances,
28 universal_regions: &UniversalRegions<'tcx>,
29 live_points: &'a SparseIntervalMatrix<RegionVid, PointIndex>,
30 ) -> Self {
31 let is_universal_region = universal_regions.is_universal_region(region);
33
34 let direction = if is_universal_region {
42 ConstraintDirection::Forward
43 } else {
44 live_region_variances
45 .get(region)
46 .copied()
47 .flatten()
48 .unwrap_or(ConstraintDirection::Bidirectional)
49 };
50 let live_points = live_points.row(region);
51 Self { direction, live_points }
52 }
53
54 pub(super) fn is_live_at(&self, point: PointIndex) -> bool {
55 self.live_points.is_some_and(|points| points.contains(point))
56 }
57}
58
59#[derive(#[automatically_derived]
impl<'tcx> ::core::default::Default for DeferredRegionLiveness<'tcx> {
#[inline]
fn default() -> Self {
DeferredRegionLiveness {
by_region: ::core::default::Default::default(),
drop_args_by_local: ::core::default::Default::default(),
}
}
}Default)]
64pub(crate) struct DeferredRegionLiveness<'tcx> {
65 by_region: IndexVec<RegionVid, Option<Local>>,
69
70 drop_args_by_local: IndexVec<Local, Option<Vec<GenericArg<'tcx>>>>,
72}
73
74impl<'tcx> DeferredRegionLiveness<'tcx> {
75 pub(crate) fn defer_local(
78 &mut self,
79 tcx: TyCtxt<'tcx>,
80 universal_regions: &UniversalRegions<'tcx>,
81 local: Local,
82 local_ty: Ty<'tcx>,
83 dropck_kinds: &[GenericArg<'tcx>],
84 ) {
85 self.drop_args_by_local.insert(local, dropck_kinds.to_vec());
89
90 tcx.for_each_free_region(&local_ty, |region| {
94 if region.is_bound() || region.is_erased() {
96 return;
97 }
98 let vid = universal_regions.to_region_vid(region);
99 let previous = self.by_region.insert(vid, local);
102 if true {
if !previous.is_none() {
{
::core::panicking::panic_fmt(format_args!("{0:?} is in the type of both {1:?} and {2:?}, but MIR renumbering should ensure that this is impossible.",
vid, previous, local));
}
};
};debug_assert!(
103 previous.is_none(),
104 "{vid:?} is in the type of both {previous:?} and {local:?}, but \
105 MIR renumbering should ensure that this is impossible.",
106 );
107 });
108 }
109
110 #[inline]
112 pub(crate) fn ensure_deferred_liveness(
113 &mut self,
114 region: RegionVid,
115 universal_regions: &UniversalRegions<'tcx>,
116 liveness: &mut LivenessValues,
117 live_region_variances: &mut LiveRegionVariances,
118 comp: &mut LivenessComputation<'_, 'tcx>,
119 ) {
120 let Some(local) = self.by_region.remove(region) else {
121 return;
122 };
123 let Some(drop_args) = self.drop_args_by_local.remove(local) else {
124 return;
125 };
126
127 comp.compute(local, universal_regions, Some(live_region_variances), liveness, || {
128 &drop_args
129 });
130 }
131}