Skip to content

Commit b05b607

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 0eca4dd commit b05b607

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;
@@ -142,6 +143,13 @@ pub(crate) fn type_check<'a, 'tcx>(
142143

143144
debug!(?normalized_inputs_and_output);
144145

146+
let mut polonius_context = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
147+
let num_regions = infcx.num_region_vars();
148+
Some(PoloniusContext::new(num_regions))
149+
} else {
150+
None
151+
};
152+
145153
let mut typeck = TypeChecker {
146154
infcx,
147155
last_span: body.span,
@@ -156,6 +164,7 @@ pub(crate) fn type_check<'a, 'tcx>(
156164
all_facts,
157165
borrow_set,
158166
constraints: &mut constraints,
167+
polonius_context: &mut polonius_context,
159168
};
160169

161170
typeck.check_user_type_annotations();
@@ -172,7 +181,12 @@ pub(crate) fn type_check<'a, 'tcx>(
172181
let opaque_type_values =
173182
opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
174183

175-
MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
184+
MirTypeckResults {
185+
constraints,
186+
universal_region_relations,
187+
opaque_type_values,
188+
polonius_context,
189+
}
176190
}
177191

178192
#[track_caller]
@@ -540,6 +554,8 @@ struct TypeChecker<'a, 'tcx> {
540554
all_facts: &'a mut Option<AllFacts>,
541555
borrow_set: &'a BorrowSet<'tcx>,
542556
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
557+
/// When using `-Zpolonius=next`, the helper data used to create polonius constraints.
558+
polonius_context: &'a mut Option<PoloniusContext>,
543559
}
544560

545561
/// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
@@ -548,6 +564,7 @@ pub(crate) struct MirTypeckResults<'tcx> {
548564
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
549565
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
550566
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
567+
pub(crate) polonius_context: Option<PoloniusContext>,
551568
}
552569

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

0 commit comments

Comments
 (0)