11use rustc_data_structures:: fx:: FxHashSet ;
22use rustc_middle:: mir:: { Body , Location , Statement , StatementKind , Terminator , TerminatorKind } ;
3- use rustc_middle:: ty:: { TyCtxt , TypeVisitable } ;
3+ use rustc_middle:: ty:: TyCtxt ;
44use rustc_mir_dataflow:: points:: PointIndex ;
55
66use super :: { LocalizedOutlivesConstraint , LocalizedOutlivesConstraintSet } ;
@@ -52,10 +52,8 @@ pub(super) fn convert_typeck_constraints<'tcx>(
5252 // this information better in MIR typeck instead, for example with a new `Locations`
5353 // variant that contains which node is crossing over between entry and exit.
5454 let point = liveness. point_from_location ( location) ;
55- let ( from, to) = if let Some ( stmt) =
56- body[ location. block ] . statements . get ( location. statement_index )
57- {
58- localize_statement_constraint (
55+ if let Some ( stmt) = body[ location. block ] . statements . get ( location. statement_index ) {
56+ convert_statement_constraint (
5957 tcx,
6058 body,
6159 stmt,
@@ -64,34 +62,30 @@ pub(super) fn convert_typeck_constraints<'tcx>(
6462 location,
6563 point,
6664 universal_regions,
65+ localized_outlives_constraints,
6766 )
6867 } else {
6968 assert_eq ! ( location. statement_index, body[ location. block] . statements. len( ) ) ;
7069 let terminator = body[ location. block ] . terminator ( ) ;
71- localize_terminator_constraint (
70+ convert_terminator_constraint (
7271 tcx,
7372 body,
7473 terminator,
7574 liveness,
7675 & outlives_constraint,
7776 point,
7877 universal_regions,
78+ localized_outlives_constraints,
7979 )
80- } ;
81- localized_outlives_constraints. push ( LocalizedOutlivesConstraint {
82- source : outlives_constraint. sup ,
83- from,
84- target : outlives_constraint. sub ,
85- to,
86- } ) ;
80+ }
8781 }
8882 }
8983 }
9084}
9185
9286/// For a given outlives constraint arising from a MIR statement, computes the CFG `from`-`to`
9387/// intra-block nodes to localize the constraint.
94- fn localize_statement_constraint < ' tcx > (
88+ fn convert_statement_constraint < ' tcx > (
9589 tcx : TyCtxt < ' tcx > ,
9690 body : & Body < ' tcx > ,
9791 stmt : & Statement < ' tcx > ,
@@ -100,7 +94,8 @@ fn localize_statement_constraint<'tcx>(
10094 current_location : Location ,
10195 current_point : PointIndex ,
10296 universal_regions : & UniversalRegions < ' tcx > ,
103- ) -> ( PointIndex , PointIndex ) {
97+ localized_outlives_constraints : & mut LocalizedOutlivesConstraintSet ,
98+ ) {
10499 match & stmt. kind {
105100 StatementKind :: Assign ( box ( lhs, rhs) ) => {
106101 // To create localized outlives constraints without midpoints, we rely on the property
@@ -146,33 +141,52 @@ fn localize_statement_constraint<'tcx>(
146141 statement_index : current_location. statement_index + 1 ,
147142 } ;
148143 let successor_point = liveness. point_from_location ( successor_location) ;
149- compute_constraint_direction (
150- tcx,
151- outlives_constraint,
152- & lhs_ty,
153- current_point,
154- successor_point,
155- universal_regions,
156- )
144+
145+ let mut from = current_point;
146+ let mut to = current_point;
147+ tcx. for_each_free_region ( & lhs_ty, |region| {
148+ let region = universal_regions. to_region_vid ( region) ;
149+ if region == outlives_constraint. sub {
150+ // This constraint flows into the LHS, its effects start becoming visible on
151+ // exit.
152+ to = successor_point;
153+ } else if region == outlives_constraint. sup {
154+ // This constraint flows from the LHS, its effects start becoming visible on
155+ // exit.
156+ from = successor_point;
157+ }
158+ } ) ;
159+ localized_outlives_constraints. push ( LocalizedOutlivesConstraint {
160+ source : outlives_constraint. sup ,
161+ from,
162+ target : outlives_constraint. sub ,
163+ to,
164+ } ) ;
157165 }
158166 _ => {
159167 // For the other cases, we localize an outlives constraint to where it arises.
160- ( current_point, current_point)
168+ localized_outlives_constraints. push ( LocalizedOutlivesConstraint {
169+ source : outlives_constraint. sup ,
170+ from : current_point,
171+ target : outlives_constraint. sub ,
172+ to : current_point,
173+ } ) ;
161174 }
162175 }
163176}
164177
165178/// For a given outlives constraint arising from a MIR terminator, computes the CFG `from`-`to`
166179/// inter-block nodes to localize the constraint.
167- fn localize_terminator_constraint < ' tcx > (
180+ fn convert_terminator_constraint < ' tcx > (
168181 tcx : TyCtxt < ' tcx > ,
169182 body : & Body < ' tcx > ,
170183 terminator : & Terminator < ' tcx > ,
171184 liveness : & LivenessValues ,
172185 outlives_constraint : & OutlivesConstraint < ' tcx > ,
173186 current_point : PointIndex ,
174187 universal_regions : & UniversalRegions < ' tcx > ,
175- ) -> ( PointIndex , PointIndex ) {
188+ localized_outlives_constraints : & mut LocalizedOutlivesConstraintSet ,
189+ ) {
176190 // FIXME: check if other terminators need the same handling as `Call`s, in particular
177191 // Assert/Yield/Drop. A handful of tests are failing with Drop related issues, as well as some
178192 // coroutine tests, and that may be why.
@@ -185,47 +199,39 @@ fn localize_terminator_constraint<'tcx>(
185199 let destination_ty = destination. ty ( & body. local_decls , tcx) ;
186200 let successor_location = Location { block : * target, statement_index : 0 } ;
187201 let successor_point = liveness. point_from_location ( successor_location) ;
188- compute_constraint_direction (
189- tcx,
190- outlives_constraint,
191- & destination_ty,
192- current_point,
193- successor_point,
194- universal_regions,
195- )
202+
203+ let mut from = current_point;
204+ let mut to = current_point;
205+ tcx. for_each_free_region ( & destination_ty, |region| {
206+ let region = universal_regions. to_region_vid ( region) ;
207+ if region == outlives_constraint. sub {
208+ // This constraint flows into the destination, its effects start becoming
209+ // visible on exit.
210+ to = successor_point;
211+ } else if region == outlives_constraint. sup {
212+ // This constraint flows from the destination, its effects start becoming
213+ // visible on exit.
214+ from = successor_point;
215+ }
216+ } ) ;
217+
218+ localized_outlives_constraints. push ( LocalizedOutlivesConstraint {
219+ source : outlives_constraint. sup ,
220+ from,
221+ target : outlives_constraint. sub ,
222+ to,
223+ } ) ;
196224 }
197225 _ => {
198226 // Typeck constraints guide loans between regions at the current point, so we do that in
199227 // the general case, and liveness will take care of making them flow to the terminator's
200228 // successors.
201- ( current_point, current_point)
229+ localized_outlives_constraints. push ( LocalizedOutlivesConstraint {
230+ source : outlives_constraint. sup ,
231+ from : current_point,
232+ target : outlives_constraint. sub ,
233+ to : current_point,
234+ } ) ;
202235 }
203236 }
204237}
205-
206- /// For a given constraint, returns the `from`-`to` edge according to whether the constraint flows
207- /// to or from a free region in the given `value`, some kind of result for an effectful operation,
208- /// like the LHS of an assignment.
209- fn compute_constraint_direction < ' tcx > (
210- tcx : TyCtxt < ' tcx > ,
211- outlives_constraint : & OutlivesConstraint < ' tcx > ,
212- value : & impl TypeVisitable < TyCtxt < ' tcx > > ,
213- current_point : PointIndex ,
214- successor_point : PointIndex ,
215- universal_regions : & UniversalRegions < ' tcx > ,
216- ) -> ( PointIndex , PointIndex ) {
217- let mut to = current_point;
218- let mut from = current_point;
219- tcx. for_each_free_region ( value, |region| {
220- let region = universal_regions. to_region_vid ( region) ;
221- if region == outlives_constraint. sub {
222- // This constraint flows into the result, its effects start becoming visible on exit.
223- to = successor_point;
224- } else if region == outlives_constraint. sup {
225- // This constraint flows from the result, its effects start becoming visible on exit.
226- from = successor_point;
227- }
228- } ) ;
229-
230- ( from, to)
231- }
0 commit comments