1
1
use itertools:: { Either , Itertools } ;
2
2
use 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 } ;
5
7
use rustc_mir_dataflow:: impls:: MaybeInitializedPlaces ;
6
8
use rustc_mir_dataflow:: move_paths:: MoveData ;
7
9
use rustc_mir_dataflow:: ResultsCursor ;
@@ -11,7 +13,7 @@ use crate::{
11
13
constraints:: OutlivesConstraintSet ,
12
14
facts:: { AllFacts , AllFactsExt } ,
13
15
location:: LocationTable ,
14
- region_infer:: values:: RegionValueElements ,
16
+ region_infer:: values:: { LivenessValues , RegionValueElements } ,
15
17
universal_regions:: UniversalRegions ,
16
18
} ;
17
19
@@ -65,6 +67,14 @@ pub(super) fn generate<'mir, 'tcx>(
65
67
boring_locals,
66
68
polonius_drop_used,
67
69
) ;
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
+ ) ;
68
78
}
69
79
70
80
// 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>(
132
142
// Return the final set of things we visited.
133
143
outlives_free_region
134
144
}
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