32
32
//! - <https://smallcultfollowing.com/babysteps/blog/2023/09/22/polonius-part-1/>
33
33
//! - <https://smallcultfollowing.com/babysteps/blog/2023/09/29/polonius-part-2/>
34
34
//!
35
+ //!
36
+ //! Data flows like this:
37
+ //! 1) during MIR typeck, record liveness data needed later: live region variances, as well as the
38
+ //! usual NLL liveness data (just computed on more locals). That's the [PoloniusLivenessContext].
39
+ //! 2) once that is done, variance data is transferred, and the NLL region liveness is converted to
40
+ //! the polonius shape. That's the main [PoloniusContext].
41
+ //! 3) during region inference, that data and the NLL outlives constraints are used to create the
42
+ //! localized outlives constraints, as described above.
43
+ //! 4) transfer these constraints back to the main borrowck procedure: it handles computing errors
44
+ //! and diagnostics, debugging and MIR dumping concerns.
35
45
36
46
mod constraints;
37
47
mod dump;
@@ -43,6 +53,7 @@ mod typeck_constraints;
43
53
use std:: collections:: BTreeMap ;
44
54
45
55
use rustc_index:: bit_set:: SparseBitMatrix ;
56
+ use rustc_index:: interval:: SparseIntervalMatrix ;
46
57
use rustc_middle:: mir:: Body ;
47
58
use rustc_middle:: ty:: { RegionVid , TyCtxt } ;
48
59
use rustc_mir_dataflow:: points:: PointIndex ;
@@ -57,11 +68,21 @@ use crate::{BorrowSet, RegionInferenceContext};
57
68
58
69
pub ( crate ) type LiveLoans = SparseBitMatrix < PointIndex , BorrowIndex > ;
59
70
60
- /// This struct holds the data needed to create the Polonius localized constraints.
71
+ /// This struct holds the liveness data created during MIR typeck, and which will be used later in
72
+ /// the process, to compute the polonius localized constraints.
73
+ #[ derive( Default ) ]
74
+ pub ( crate ) struct PoloniusLivenessContext {
75
+ /// The expected edge direction per live region: the kind of directed edge we'll create as
76
+ /// liveness constraints depends on the variance of types with respect to each contained region.
77
+ live_region_variances : BTreeMap < RegionVid , ConstraintDirection > ,
78
+ }
79
+
80
+ /// This struct holds the data needed to create the Polonius localized constraints. Its data is
81
+ /// transferred and converted from the [PoloniusLivenessContext] at the end of MIR typeck.
61
82
pub ( crate ) struct PoloniusContext {
62
83
/// The set of regions that are live at a given point in the CFG, used to create localized
63
84
/// outlives constraints between regions that are live at connected points in the CFG.
64
- live_regions : Option < SparseBitMatrix < PointIndex , RegionVid > > ,
85
+ live_regions : SparseBitMatrix < PointIndex , RegionVid > ,
65
86
66
87
/// The expected edge direction per live region: the kind of directed edge we'll create as
67
88
/// liveness constraints depends on the variance of types with respect to each contained region.
@@ -83,8 +104,27 @@ enum ConstraintDirection {
83
104
}
84
105
85
106
impl PoloniusContext {
86
- pub ( crate ) fn new ( ) -> PoloniusContext {
87
- Self { live_region_variances : BTreeMap :: new ( ) , live_regions : None }
107
+ /// Unlike NLLs, in polonius we traverse the cfg to look for regions live across an edge, so we
108
+ /// need to transpose the "points where each region is live" matrix to a "live regions per point"
109
+ /// matrix.
110
+ // FIXME: avoid this conversion by always storing liveness data in this shape in the rest of
111
+ // borrowck.
112
+ pub ( crate ) fn create_from_liveness (
113
+ liveness_context : PoloniusLivenessContext ,
114
+ num_regions : usize ,
115
+ points_per_live_region : & SparseIntervalMatrix < RegionVid , PointIndex > ,
116
+ ) -> PoloniusContext {
117
+ let mut live_regions_per_point = SparseBitMatrix :: new ( num_regions) ;
118
+ for region in points_per_live_region. rows ( ) {
119
+ for point in points_per_live_region. row ( region) . unwrap ( ) . iter ( ) {
120
+ live_regions_per_point. insert ( point, region) ;
121
+ }
122
+ }
123
+
124
+ PoloniusContext {
125
+ live_regions : live_regions_per_point,
126
+ live_region_variances : liveness_context. live_region_variances ,
127
+ }
88
128
}
89
129
90
130
/// Computes live loans using the set of loans model for `-Zpolonius=next`.
@@ -112,13 +152,10 @@ impl PoloniusContext {
112
152
& mut localized_outlives_constraints,
113
153
) ;
114
154
115
- let live_regions = self . live_regions . as_ref ( ) . expect (
116
- "live regions per-point data should have been created at the end of MIR typeck" ,
117
- ) ;
118
155
create_liveness_constraints (
119
156
body,
120
157
regioncx. liveness_constraints ( ) ,
121
- live_regions,
158
+ & self . live_regions ,
122
159
& self . live_region_variances ,
123
160
regioncx. universal_regions ( ) ,
124
161
& mut localized_outlives_constraints,
0 commit comments