11use itertools:: { Either , Itertools } ;
22use rustc_data_structures:: fx:: FxHashSet ;
3- use rustc_middle:: mir:: { Body , Local } ;
4- use rustc_middle:: ty:: { RegionVid , TyCtxt } ;
3+ use rustc_middle:: mir:: visit:: { TyContext , Visitor } ;
4+ use rustc_middle:: mir:: { Body , Local , Location , SourceInfo } ;
5+ use rustc_middle:: ty:: visit:: TypeVisitable ;
6+ use rustc_middle:: ty:: { GenericArgsRef , Region , RegionVid , Ty , TyCtxt } ;
57use rustc_mir_dataflow:: impls:: MaybeInitializedPlaces ;
68use rustc_mir_dataflow:: move_paths:: MoveData ;
79use rustc_mir_dataflow:: ResultsCursor ;
@@ -11,7 +13,7 @@ use crate::{
1113 constraints:: OutlivesConstraintSet ,
1214 facts:: { AllFacts , AllFactsExt } ,
1315 location:: LocationTable ,
14- region_infer:: values:: RegionValueElements ,
16+ region_infer:: values:: { LivenessValues , RegionValueElements } ,
1517 universal_regions:: UniversalRegions ,
1618} ;
1719
@@ -65,6 +67,14 @@ pub(super) fn generate<'mir, 'tcx>(
6567 boring_locals,
6668 polonius_drop_used,
6769 ) ;
70+
71+ // Mark regions that should be live where they appear within rvalues or within a call: like
72+ // args, regions, and types.
73+ record_regular_live_regions (
74+ typeck. tcx ( ) ,
75+ & mut typeck. borrowck_context . constraints . liveness_constraints ,
76+ body,
77+ ) ;
6878}
6979
7080// The purpose of `compute_relevant_live_locals` is to define the subset of `Local`
@@ -132,3 +142,71 @@ fn regions_that_outlive_free_regions<'tcx>(
132142 // Return the final set of things we visited.
133143 outlives_free_region
134144}
145+
146+ /// Some variables are "regular live" at `location` -- i.e., they may be used later. This means that
147+ /// all regions appearing in their type must be live at `location`.
148+ fn record_regular_live_regions < ' tcx > (
149+ tcx : TyCtxt < ' tcx > ,
150+ liveness_constraints : & mut LivenessValues ,
151+ body : & Body < ' tcx > ,
152+ ) {
153+ let mut visitor = LiveVariablesVisitor { tcx, liveness_constraints } ;
154+ for ( bb, data) in body. basic_blocks . iter_enumerated ( ) {
155+ visitor. visit_basic_block_data ( bb, data) ;
156+ }
157+ }
158+
159+ /// Visitor looking for regions that should be live within rvalues or calls.
160+ struct LiveVariablesVisitor < ' cx , ' tcx > {
161+ tcx : TyCtxt < ' tcx > ,
162+ liveness_constraints : & ' cx mut LivenessValues ,
163+ }
164+
165+ impl < ' cx , ' tcx > Visitor < ' tcx > for LiveVariablesVisitor < ' cx , ' tcx > {
166+ /// We sometimes have `args` within an rvalue, or within a
167+ /// call. Make them live at the location where they appear.
168+ fn visit_args ( & mut self , args : & GenericArgsRef < ' tcx > , location : Location ) {
169+ self . record_regions_live_at ( * args, location) ;
170+ self . super_args ( args) ;
171+ }
172+
173+ /// We sometimes have `region`s within an rvalue, or within a
174+ /// call. Make them live at the location where they appear.
175+ fn visit_region ( & mut self , region : Region < ' tcx > , location : Location ) {
176+ self . record_regions_live_at ( region, location) ;
177+ self . super_region ( region) ;
178+ }
179+
180+ /// We sometimes have `ty`s within an rvalue, or within a
181+ /// call. Make them live at the location where they appear.
182+ fn visit_ty ( & mut self , ty : Ty < ' tcx > , ty_context : TyContext ) {
183+ match ty_context {
184+ TyContext :: ReturnTy ( SourceInfo { span, .. } )
185+ | TyContext :: YieldTy ( SourceInfo { span, .. } )
186+ | TyContext :: UserTy ( span)
187+ | TyContext :: LocalDecl { source_info : SourceInfo { span, .. } , .. } => {
188+ span_bug ! ( span, "should not be visiting outside of the CFG: {:?}" , ty_context) ;
189+ }
190+ TyContext :: Location ( location) => {
191+ self . record_regions_live_at ( ty, location) ;
192+ }
193+ }
194+
195+ self . super_ty ( ty) ;
196+ }
197+ }
198+
199+ impl < ' cx , ' tcx > LiveVariablesVisitor < ' cx , ' tcx > {
200+ /// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
201+ /// all regions appearing in the type of `value` must be live at `location`.
202+ fn record_regions_live_at < T > ( & mut self , value : T , location : Location )
203+ where
204+ T : TypeVisitable < TyCtxt < ' tcx > > ,
205+ {
206+ debug ! ( "record_regions_live_at(value={:?}, location={:?})" , value, location) ;
207+ self . tcx . for_each_free_region ( & value, |live_region| {
208+ let live_region_vid = live_region. as_var ( ) ;
209+ self . liveness_constraints . add_location ( live_region_vid, location) ;
210+ } ) ;
211+ }
212+ }
0 commit comments