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.map_or(false, |points| points.contains(point))
56 }
57}
58
59#[derive(#[automatically_derived]
impl<'tcx> ::core::default::Default for DeferredLocals<'tcx> {
#[inline]
fn default() -> Self {
Self {
by_region: ::core::default::Default::default(),
drop_args_by_local: ::core::default::Default::default(),
}
}
}Default)]
62pub(crate) struct DeferredLocals<'tcx> {
63 by_region: IndexVec<RegionVid, Option<Local>>,
67
68 drop_args_by_local: IndexVec<Local, Option<Vec<GenericArg<'tcx>>>>,
70}
71
72impl<'tcx> DeferredLocals<'tcx> {
73 pub(crate) fn defer_local(
74 &mut self,
75 tcx: TyCtxt<'tcx>,
76 universal_regions: &UniversalRegions<'tcx>,
77 local: Local,
78 local_ty: Ty<'tcx>,
79 dropck_kinds: &[GenericArg<'tcx>],
80 ) {
81 self.drop_args_by_local.insert(local, dropck_kinds.to_vec());
85
86 let by_region = &mut self.by_region;
90 tcx.for_each_free_region(&local_ty, |region| {
91 if region.is_bound() || region.is_erased() {
93 return;
94 }
95 let vid = universal_regions.to_region_vid(region);
96 let previous = by_region.insert(vid, local);
99 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!(
100 previous.is_none(),
101 "{vid:?} is in the type of both {previous:?} and {local:?}, but \
102 MIR renumbering should ensure that this is impossible.",
103 );
104 });
105 }
106
107 #[inline]
109 pub(crate) fn compute_deferred_local(
110 &mut self,
111 region: RegionVid,
112 universal_regions: &UniversalRegions<'tcx>,
113 liveness: &mut LivenessValues,
114 live_region_variances: &mut LiveRegionVariances,
115 comp: &mut LivenessComputation<'_, 'tcx>,
116 ) {
117 let Some(local) = self.by_region.remove(region) else {
118 return;
119 };
120 let Some(drop_args) = self.drop_args_by_local.remove(local) else {
121 return;
122 };
123
124 comp.compute(local, universal_regions, Some(live_region_variances), liveness, || {
125 &drop_args
126 });
127 }
128}