@@ -220,6 +220,78 @@ impl LivenessResult {
220
220
}
221
221
}
222
222
223
+ #[ derive( Eq , PartialEq , Clone ) ]
224
+ pub enum DefUse {
225
+ Def ,
226
+ Use ,
227
+ }
228
+
229
+ pub fn categorize < ' tcx > ( context : PlaceContext < ' tcx > , mode : LivenessMode ) -> Option < DefUse > {
230
+ match context {
231
+ ///////////////////////////////////////////////////////////////////////////
232
+ // DEFS
233
+
234
+ PlaceContext :: Store |
235
+
236
+ // We let Call define the result in both the success and
237
+ // unwind cases. This is not really correct, however it
238
+ // does not seem to be observable due to the way that we
239
+ // generate MIR. See the test case
240
+ // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
241
+ // properly, we would apply the def in call only to the
242
+ // input from the success path and not the unwind
243
+ // path. -nmatsakis
244
+ PlaceContext :: Call |
245
+
246
+ // Storage live and storage dead aren't proper defines, but we can ignore
247
+ // values that come before them.
248
+ PlaceContext :: StorageLive |
249
+ PlaceContext :: StorageDead => Some ( DefUse :: Def ) ,
250
+
251
+ ///////////////////////////////////////////////////////////////////////////
252
+ // REGULAR USES
253
+ //
254
+ // These are uses that occur *outside* of a drop. For the
255
+ // purposes of NLL, these are special in that **all** the
256
+ // lifetimes appearing in the variable must be live for each regular use.
257
+
258
+ PlaceContext :: Projection ( ..) |
259
+
260
+ // Borrows only consider their local used at the point of the borrow.
261
+ // This won't affect the results since we use this analysis for generators
262
+ // and we only care about the result at suspension points. Borrows cannot
263
+ // cross suspension points so this behavior is unproblematic.
264
+ PlaceContext :: Borrow { .. } |
265
+
266
+ PlaceContext :: Inspect |
267
+ PlaceContext :: Copy |
268
+ PlaceContext :: Move |
269
+ PlaceContext :: Validate => {
270
+ if mode. include_regular_use {
271
+ Some ( DefUse :: Use )
272
+ } else {
273
+ None
274
+ }
275
+ }
276
+
277
+ ///////////////////////////////////////////////////////////////////////////
278
+ // DROP USES
279
+ //
280
+ // These are uses that occur in a DROP (a MIR drop, not a
281
+ // call to `std::mem::drop()`). For the purposes of NLL,
282
+ // uses in drop are special because `#[may_dangle]`
283
+ // attributes can affect whether lifetimes must be live.
284
+
285
+ PlaceContext :: Drop => {
286
+ if mode. include_drops {
287
+ Some ( DefUse :: Use )
288
+ } else {
289
+ None
290
+ }
291
+ }
292
+ }
293
+ }
294
+
223
295
struct DefsUsesVisitor {
224
296
mode : LivenessMode ,
225
297
defs_uses : DefsUses ,
@@ -268,66 +340,16 @@ impl DefsUses {
268
340
269
341
impl < ' tcx > Visitor < ' tcx > for DefsUsesVisitor {
270
342
fn visit_local ( & mut self , & local: & Local , context : PlaceContext < ' tcx > , _: Location ) {
271
- match context {
272
- ///////////////////////////////////////////////////////////////////////////
273
- // DEFS
274
-
275
- PlaceContext :: Store |
276
-
277
- // We let Call define the result in both the success and
278
- // unwind cases. This is not really correct, however it
279
- // does not seem to be observable due to the way that we
280
- // generate MIR. See the test case
281
- // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
282
- // properly, we would apply the def in call only to the
283
- // input from the success path and not the unwind
284
- // path. -nmatsakis
285
- PlaceContext :: Call |
286
-
287
- // Storage live and storage dead aren't proper defines, but we can ignore
288
- // values that come before them.
289
- PlaceContext :: StorageLive |
290
- PlaceContext :: StorageDead => {
343
+ match categorize ( context, self . mode ) {
344
+ Some ( DefUse :: Def ) => {
291
345
self . defs_uses . add_def ( local) ;
292
346
}
293
347
294
- ///////////////////////////////////////////////////////////////////////////
295
- // REGULAR USES
296
- //
297
- // These are uses that occur *outside* of a drop. For the
298
- // purposes of NLL, these are special in that **all** the
299
- // lifetimes appearing in the variable must be live for each regular use.
300
-
301
- PlaceContext :: Projection ( ..) |
302
-
303
- // Borrows only consider their local used at the point of the borrow.
304
- // This won't affect the results since we use this analysis for generators
305
- // and we only care about the result at suspension points. Borrows cannot
306
- // cross suspension points so this behavior is unproblematic.
307
- PlaceContext :: Borrow { .. } |
308
-
309
- PlaceContext :: Inspect |
310
- PlaceContext :: Copy |
311
- PlaceContext :: Move |
312
- PlaceContext :: Validate => {
313
- if self . mode . include_regular_use {
314
- self . defs_uses . add_use ( local) ;
315
- }
348
+ Some ( DefUse :: Use ) => {
349
+ self . defs_uses . add_use ( local) ;
316
350
}
317
351
318
- ///////////////////////////////////////////////////////////////////////////
319
- // DROP USES
320
- //
321
- // These are uses that occur in a DROP (a MIR drop, not a
322
- // call to `std::mem::drop()`). For the purposes of NLL,
323
- // uses in drop are special because `#[may_dangle]`
324
- // attributes can affect whether lifetimes must be live.
325
-
326
- PlaceContext :: Drop => {
327
- if self . mode . include_drops {
328
- self . defs_uses . add_use ( local) ;
329
- }
330
- }
352
+ None => { }
331
353
}
332
354
}
333
355
}
0 commit comments