Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 27a5b86

Browse files
committed
introduce polonius context
This context struct will hold data to help creating localized constraints: - the live regions, with the shape matching a CFG walk, indexed per point - the variance of these live regions, represented as the direction we'll add the appropriate We also add this structure to the mir typeck to record liveness data, and make it responsible for localized constraint creation.
1 parent b22856d commit 27a5b86

File tree

3 files changed

+104
-47
lines changed

3 files changed

+104
-47
lines changed

compiler/rustc_borrowck/src/nll.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,23 @@ pub(crate) fn compute_regions<'a, 'tcx>(
100100
let elements = Rc::new(DenseLocationMap::new(body));
101101

102102
// Run the MIR type-checker.
103-
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
104-
type_check::type_check(
105-
infcx,
106-
body,
107-
promoted,
108-
universal_regions,
109-
location_table,
110-
borrow_set,
111-
&mut all_facts,
112-
flow_inits,
113-
move_data,
114-
Rc::clone(&elements),
115-
);
103+
let MirTypeckResults {
104+
constraints,
105+
universal_region_relations,
106+
opaque_type_values,
107+
mut polonius_context,
108+
} = type_check::type_check(
109+
infcx,
110+
body,
111+
promoted,
112+
universal_regions,
113+
location_table,
114+
borrow_set,
115+
&mut all_facts,
116+
flow_inits,
117+
move_data,
118+
Rc::clone(&elements),
119+
);
116120

117121
// Create the region inference context, taking ownership of the
118122
// region inference data that was contained in `infcx`, and the
@@ -141,12 +145,9 @@ pub(crate) fn compute_regions<'a, 'tcx>(
141145

142146
// If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives
143147
// constraints.
144-
let localized_outlives_constraints =
145-
if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
146-
Some(polonius::create_localized_constraints(&mut regioncx, body))
147-
} else {
148-
None
149-
};
148+
let localized_outlives_constraints = polonius_context
149+
.as_mut()
150+
.map(|polonius_context| polonius_context.create_localized_constraints(&mut regioncx, body));
150151

151152
// If requested: dump NLL facts, and run legacy polonius analysis.
152153
let polonius_output = all_facts.as_ref().and_then(|all_facts| {

compiler/rustc_borrowck/src/polonius/mod.rs

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,45 +34,84 @@
3434
//!
3535
3636
mod constraints;
37-
pub(crate) use constraints::*;
3837
mod dump;
39-
pub(crate) use dump::dump_polonius_mir;
4038
pub(crate) mod legacy;
4139

40+
use std::collections::BTreeMap;
41+
42+
use rustc_index::bit_set::SparseBitMatrix;
4243
use rustc_middle::mir::{Body, Location};
44+
use rustc_middle::ty::RegionVid;
4345
use rustc_mir_dataflow::points::PointIndex;
4446

47+
pub(crate) use self::constraints::*;
48+
pub(crate) use self::dump::dump_polonius_mir;
4549
use crate::RegionInferenceContext;
4650
use crate::constraints::OutlivesConstraint;
4751
use crate::region_infer::values::LivenessValues;
4852
use crate::type_check::Locations;
4953
use crate::universal_regions::UniversalRegions;
5054

51-
/// Creates a constraint set for `-Zpolonius=next` by:
52-
/// - converting NLL typeck constraints to be localized
53-
/// - encoding liveness constraints
54-
pub(crate) fn create_localized_constraints<'tcx>(
55-
regioncx: &mut RegionInferenceContext<'tcx>,
56-
body: &Body<'tcx>,
57-
) -> LocalizedOutlivesConstraintSet {
58-
let mut localized_outlives_constraints = LocalizedOutlivesConstraintSet::default();
59-
convert_typeck_constraints(
60-
body,
61-
regioncx.liveness_constraints(),
62-
regioncx.outlives_constraints(),
63-
&mut localized_outlives_constraints,
64-
);
65-
create_liveness_constraints(
66-
body,
67-
regioncx.liveness_constraints(),
68-
regioncx.universal_regions(),
69-
&mut localized_outlives_constraints,
70-
);
71-
72-
// FIXME: here, we can trace loan reachability in the constraint graph and record this as loan
73-
// liveness for the next step in the chain, the NLL loan scope and active loans computations.
74-
75-
localized_outlives_constraints
55+
/// This struct holds the data needed to create the Polonius localized constraints.
56+
pub(crate) struct PoloniusContext {
57+
/// The set of regions that are live at a given point in the CFG, used to create localized
58+
/// outlives constraints between regions that are live at connected points in the CFG.
59+
live_regions: SparseBitMatrix<PointIndex, RegionVid>,
60+
61+
/// The expected edge direction per live region: the kind of directed edge we'll create as
62+
/// liveness constraints depends on the variance of types with respect to each contained region.
63+
live_region_variances: BTreeMap<RegionVid, ConstraintDirection>,
64+
}
65+
66+
/// The direction a constraint can flow into. Used to create liveness constraints according to
67+
/// variance.
68+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
69+
enum ConstraintDirection {
70+
/// For covariant cases, we add a forward edge `O at P1 -> O at P2`.
71+
Forward,
72+
73+
/// For contravariant cases, we add a backward edge `O at P2 -> O at P1`
74+
Backward,
75+
76+
/// For invariant cases, we add both the forward and backward edges `O at P1 <-> O at P2`.
77+
Bidirectional,
78+
}
79+
80+
impl PoloniusContext {
81+
pub(crate) fn new(num_regions: usize) -> PoloniusContext {
82+
Self {
83+
live_region_variances: BTreeMap::new(),
84+
live_regions: SparseBitMatrix::new(num_regions),
85+
}
86+
}
87+
88+
/// Creates a constraint set for `-Zpolonius=next` by:
89+
/// - converting NLL typeck constraints to be localized
90+
/// - encoding liveness constraints
91+
pub(crate) fn create_localized_constraints<'tcx>(
92+
&self,
93+
regioncx: &mut RegionInferenceContext<'tcx>,
94+
body: &Body<'tcx>,
95+
) -> LocalizedOutlivesConstraintSet {
96+
let mut localized_outlives_constraints = LocalizedOutlivesConstraintSet::default();
97+
convert_typeck_constraints(
98+
body,
99+
regioncx.liveness_constraints(),
100+
regioncx.outlives_constraints(),
101+
&mut localized_outlives_constraints,
102+
);
103+
create_liveness_constraints(
104+
body,
105+
regioncx.liveness_constraints(),
106+
regioncx.universal_regions(),
107+
&mut localized_outlives_constraints,
108+
);
109+
110+
// FIXME: here, we can trace loan reachability in the constraint graph and record this as loan
111+
// liveness for the next step in the chain, the NLL loan scope and active loans computations.
112+
113+
localized_outlives_constraints
114+
}
76115
}
77116

78117
/// Propagate loans throughout the subset graph at a given point (with some subtleties around the

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use crate::diagnostics::UniverseInfo;
5050
use crate::facts::AllFacts;
5151
use crate::location::LocationTable;
5252
use crate::member_constraints::MemberConstraintSet;
53+
use crate::polonius::PoloniusContext;
5354
use crate::region_infer::TypeTest;
5455
use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
5556
use crate::renumber::RegionCtxt;
@@ -151,6 +152,13 @@ pub(crate) fn type_check<'a, 'tcx>(
151152

152153
debug!(?normalized_inputs_and_output);
153154

155+
let mut polonius_context = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
156+
let num_regions = infcx.num_region_vars();
157+
Some(PoloniusContext::new(num_regions))
158+
} else {
159+
None
160+
};
161+
154162
let mut typeck = TypeChecker {
155163
infcx,
156164
last_span: body.span,
@@ -165,6 +173,7 @@ pub(crate) fn type_check<'a, 'tcx>(
165173
all_facts,
166174
borrow_set,
167175
constraints: &mut constraints,
176+
polonius_context: &mut polonius_context,
168177
};
169178

170179
typeck.check_user_type_annotations();
@@ -181,7 +190,12 @@ pub(crate) fn type_check<'a, 'tcx>(
181190
let opaque_type_values =
182191
opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
183192

184-
MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
193+
MirTypeckResults {
194+
constraints,
195+
universal_region_relations,
196+
opaque_type_values,
197+
polonius_context,
198+
}
185199
}
186200

187201
#[track_caller]
@@ -773,6 +787,8 @@ struct TypeChecker<'a, 'tcx> {
773787
all_facts: &'a mut Option<AllFacts>,
774788
borrow_set: &'a BorrowSet<'tcx>,
775789
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
790+
/// When using `-Zpolonius=next`, the helper data used to create polonius constraints.
791+
polonius_context: &'a mut Option<PoloniusContext>,
776792
}
777793

778794
/// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
@@ -781,6 +797,7 @@ pub(crate) struct MirTypeckResults<'tcx> {
781797
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
782798
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
783799
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
800+
pub(crate) polonius_context: Option<PoloniusContext>,
784801
}
785802

786803
/// A collection of region constraints that must be satisfied for the

0 commit comments

Comments
 (0)