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