@@ -2,15 +2,14 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
22use rustc_index:: IndexVec ;
33use rustc_middle:: mir:: { Body , Location } ;
44use rustc_middle:: ty:: RegionVid ;
5- use rustc_mir_dataflow:: points:: PointIndex ;
5+ use rustc_mir_dataflow:: points:: { DenseLocationMap , PointIndex } ;
66
77use crate :: BorrowSet ;
88use crate :: constraints:: OutlivesConstraint ;
99use crate :: dataflow:: BorrowIndex ;
10- use crate :: polonius:: { ConstraintDirection , LiveRegionVariances } ;
11- use crate :: region_infer :: values :: LivenessValues ;
10+ use crate :: polonius:: ConstraintDirection ;
11+ use crate :: polonius :: liveness :: RegionLiveness ;
1212use crate :: type_check:: Locations ;
13- use crate :: universal_regions:: UniversalRegions ;
1413
1514/// A localized outlives constraint reifies the CFG location where the outlives constraint holds,
1615/// within the origins themselves as if they were different from point to point: from `a: b`
@@ -49,11 +48,17 @@ pub(super) struct LocalizedConstraintGraph {
4948 logical_edges : IndexVec < RegionVid , FxIndexSet < RegionVid > > ,
5049}
5150
51+ /// The source of liveness information for a given region.
52+ pub ( super ) trait LivenessSource < ' loc > {
53+ fn liveness_for_region ( & mut self , region : RegionVid ) -> RegionLiveness < ' _ > ;
54+ fn location_map ( & self ) -> & ' loc DenseLocationMap ;
55+ }
56+
5257/// The visitor interface when traversing a `LocalizedConstraintGraph`.
5358pub ( super ) trait LocalizedConstraintGraphVisitor {
5459 /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't
5560 /// visited before.
56- fn on_node_traversed ( & mut self , _loan : BorrowIndex , _node : LocalizedNode ) { }
61+ fn on_node_traversed ( & mut self , _loan : BorrowIndex , _node : LocalizedNode , _is_live : bool ) { }
5762
5863 /// Callback called when discovering a new `successor` node for the `current_node`.
5964 fn on_successor_discovered ( & mut self , _current_node : LocalizedNode , _successor : LocalizedNode ) {
@@ -63,7 +68,7 @@ pub(super) trait LocalizedConstraintGraphVisitor {
6368impl LocalizedConstraintGraph {
6469 /// Traverses the constraints and returns the indexed graph of edges per node.
6570 pub ( super ) fn new < ' tcx > (
66- liveness : & LivenessValues ,
71+ location_map : & DenseLocationMap ,
6772 outlives_constraints : impl Iterator < Item = OutlivesConstraint < ' tcx > > ,
6873 ) -> Self {
6974 let mut edges: FxHashMap < _ , FxIndexSet < _ > > = FxHashMap :: default ( ) ;
@@ -80,7 +85,7 @@ impl LocalizedConstraintGraph {
8085 Locations :: Single ( location) => {
8186 let node = LocalizedNode {
8287 region : outlives_constraint. sup ,
83- point : liveness . point_from_location ( location) ,
88+ point : location_map . point_from_location ( location) ,
8489 } ;
8590 edges. entry ( node) . or_default ( ) . insert ( outlives_constraint. sub ) ;
8691 }
@@ -92,20 +97,18 @@ impl LocalizedConstraintGraph {
9297
9398 /// Traverses the localized constraint graph per-loan, and notifies the `visitor` of discovered
9499 /// nodes and successors.
95- pub ( super ) fn traverse < ' tcx > (
100+ pub ( super ) fn traverse < ' tcx , ' loc > (
96101 & self ,
97102 body : & Body < ' tcx > ,
98- liveness : & LivenessValues ,
99- live_region_variances : & LiveRegionVariances ,
100- universal_regions : & UniversalRegions < ' tcx > ,
101103 borrow_set : & BorrowSet < ' tcx > ,
104+ liveness_source : & mut impl LivenessSource < ' loc > ,
102105 visitor : & mut impl LocalizedConstraintGraphVisitor ,
103106 ) {
104- let live_regions = liveness. points ( ) ;
105-
106107 let mut visited = FxHashSet :: default ( ) ;
107108 let mut stack = Vec :: new ( ) ;
108109
110+ let location_map = liveness_source. location_map ( ) ;
111+
109112 // Compute reachability per loan by traversing each loan's subgraph starting from where it
110113 // is introduced.
111114 for ( loan_idx, loan) in borrow_set. iter_enumerated ( ) {
@@ -114,15 +117,16 @@ impl LocalizedConstraintGraph {
114117
115118 let start_node = LocalizedNode {
116119 region : loan. region ,
117- point : liveness . point_from_location ( loan. reserve_location ) ,
120+ point : location_map . point_from_location ( loan. reserve_location ) ,
118121 } ;
119122 visited. insert ( start_node) ;
120123 stack. push ( start_node) ;
121124
122125 while let Some ( node) = stack. pop ( ) {
126+ let liveness = liveness_source. liveness_for_region ( node. region ) ;
123127 // We've reached a node we haven't visited before.
124- let location = liveness . location_from_point ( node. point ) ;
125- visitor. on_node_traversed ( loan_idx, node) ;
128+ let location = location_map . to_location ( node. point ) ;
129+ visitor. on_node_traversed ( loan_idx, node, liveness . is_live_at ( node . point ) ) ;
126130
127131 // When we find a _new_ successor, we'd like to
128132 // - visit it eventually,
@@ -140,26 +144,6 @@ impl LocalizedConstraintGraph {
140144 // - the materialized logical edges that exist virtually at all points for this
141145 // node's region, localized at this point.
142146
143- // Universal regions propagate loans along the CFG, i.e. forwards only.
144- let is_universal_region = universal_regions. is_universal_region ( node. region ) ;
145-
146- // Note: there currently are cases related to promoted and const generics, where we don't yet
147- // have variance information (possibly about temporary regions created when typeck sanitizes the
148- // promoteds). Until that is done, we conservatively fallback to maximizing reachability by
149- // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus
150- // propagate liveness when needed.
151- //
152- // FIXME: add the missing variance information and remove this fallback bidirectional edge.
153- let liveness_direction = if is_universal_region {
154- ConstraintDirection :: Forward
155- } else {
156- live_region_variances
157- . get ( node. region )
158- . copied ( )
159- . flatten ( )
160- . unwrap_or ( ConstraintDirection :: Bidirectional )
161- } ;
162-
163147 // The physical edges present at this node are:
164148 //
165149 // 1. the typeck edges that flow from region to region *at this point*.
@@ -178,14 +162,14 @@ impl LocalizedConstraintGraph {
178162 //
179163 // We still need to check liveness for each next point though.
180164 if matches ! (
181- liveness_direction ,
165+ liveness . direction ,
182166 ConstraintDirection :: Forward | ConstraintDirection :: Bidirectional
183167 ) {
184168 if body[ location. block ] . statements . get ( location. statement_index ) . is_some ( ) {
185169 // Intra-block edges, straight line constraints from each point to its successor
186170 // within the same block.
187171 let next_point = node. point + 1 ;
188- if live_regions . contains ( node . region , next_point) {
172+ if liveness . is_live_at ( next_point) {
189173 successor_found ( LocalizedNode {
190174 region : node. region ,
191175 point : next_point,
@@ -197,8 +181,8 @@ impl LocalizedConstraintGraph {
197181 for successor_block in body[ location. block ] . terminator ( ) . successors ( ) {
198182 let next_location =
199183 Location { block : successor_block, statement_index : 0 } ;
200- let next_point = liveness . point_from_location ( next_location) ;
201- if live_regions . contains ( node . region , next_point) {
184+ let next_point = location_map . point_from_location ( next_location) ;
185+ if liveness . is_live_at ( next_point) {
202186 successor_found ( LocalizedNode {
203187 region : node. region ,
204188 point : next_point,
@@ -219,9 +203,9 @@ impl LocalizedConstraintGraph {
219203 // Liveness flows into the regions live at the next point. So, in a backwards view, we'll link
220204 // the region from the current point, if it's live there, to the previous point.
221205 if matches ! (
222- liveness_direction ,
206+ liveness . direction ,
223207 ConstraintDirection :: Backward | ConstraintDirection :: Bidirectional
224- ) && live_regions . contains ( node . region , node. point )
208+ ) && liveness . is_live_at ( node. point )
225209 {
226210 if location. statement_index > 0 {
227211 // Backward edges to the predecessor point in the same block.
@@ -239,7 +223,8 @@ impl LocalizedConstraintGraph {
239223 block : pred_block,
240224 statement_index : body[ pred_block] . statements . len ( ) ,
241225 } ;
242- let previous_point = liveness. point_from_location ( previous_location) ;
226+ let previous_point =
227+ location_map. point_from_location ( previous_location) ;
243228 successor_found ( LocalizedNode {
244229 region : node. region ,
245230 point : previous_point,
0 commit comments