Skip to content

Commit 42f28cb

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 64feb9b commit 42f28cb

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: &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;
@@ -148,6 +149,13 @@ pub(crate) fn type_check<'a, 'tcx>(
148149

149150
debug!(?normalized_inputs_and_output);
150151

152+
let mut polonius_context = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
153+
let num_regions = infcx.num_region_vars();
154+
Some(PoloniusContext::new(num_regions))
155+
} else {
156+
None
157+
};
158+
151159
let mut typeck = TypeChecker {
152160
infcx,
153161
last_span: body.span,
@@ -162,6 +170,7 @@ pub(crate) fn type_check<'a, 'tcx>(
162170
all_facts,
163171
borrow_set,
164172
constraints: &mut constraints,
173+
polonius_context: &mut polonius_context,
165174
};
166175

167176
typeck.check_user_type_annotations();
@@ -178,7 +187,12 @@ pub(crate) fn type_check<'a, 'tcx>(
178187
let opaque_type_values =
179188
opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
180189

181-
MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
190+
MirTypeckResults {
191+
constraints,
192+
universal_region_relations,
193+
opaque_type_values,
194+
polonius_context,
195+
}
182196
}
183197

184198
#[track_caller]
@@ -546,6 +560,8 @@ struct TypeChecker<'a, 'tcx> {
546560
all_facts: &'a mut Option<AllFacts>,
547561
borrow_set: &'a BorrowSet<'tcx>,
548562
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
563+
/// When using `-Zpolonius=next`, the helper data used to create polonius constraints.
564+
polonius_context: &'a mut Option<PoloniusContext>,
549565
}
550566

551567
/// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
@@ -554,6 +570,7 @@ pub(crate) struct MirTypeckResults<'tcx> {
554570
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
555571
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
556572
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
573+
pub(crate) polonius_context: Option<PoloniusContext>,
557574
}
558575

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

0 commit comments

Comments
 (0)