@@ -2,7 +2,9 @@ use crate::borrow_check::ArtificialField;
2
2
use crate :: borrow_check:: Overlap ;
3
3
use crate :: borrow_check:: { Deep , Shallow , AccessDepth } ;
4
4
use rustc:: hir;
5
- use rustc:: mir:: { BorrowKind , Mir , Place , PlaceBase , Projection , ProjectionElem } ;
5
+ use rustc:: mir:: {
6
+ BorrowKind , Mir , Place , PlaceBase , Projection , ProjectionElem , PlaceComponentsIter
7
+ } ;
6
8
use rustc:: ty:: { self , TyCtxt } ;
7
9
use std:: cmp:: max;
8
10
@@ -65,8 +67,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
65
67
}
66
68
}
67
69
68
- unroll_place ( borrow_place, None , |borrow_components| {
69
- unroll_place ( access_place, None , |access_components| {
70
+ borrow_place. unroll ( None , |borrow_components| {
71
+ access_place. unroll ( None , |access_components| {
70
72
place_components_conflict (
71
73
tcx,
72
74
mir,
@@ -272,83 +274,6 @@ fn place_components_conflict<'gcx, 'tcx>(
272
274
}
273
275
}
274
276
275
- /// A linked list of places running up the stack; begins with the
276
- /// innermost place and extends to projections (e.g., `a.b` would have
277
- /// the place `a` with a "next" pointer to `a.b`). Created by
278
- /// `unroll_place`.
279
- ///
280
- /// N.B., this particular impl strategy is not the most obvious. It was
281
- /// chosen because it makes a measurable difference to NLL
282
- /// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
283
- struct PlaceComponents < ' p , ' tcx : ' p > {
284
- component : & ' p Place < ' tcx > ,
285
- next : Option < & ' p PlaceComponents < ' p , ' tcx > > ,
286
- }
287
-
288
- impl < ' p , ' tcx > PlaceComponents < ' p , ' tcx > {
289
- /// Converts a list of `Place` components into an iterator; this
290
- /// iterator yields up a never-ending stream of `Option<&Place>`.
291
- /// These begin with the "innermost" place and then with each
292
- /// projection therefrom. So given a place like `a.b.c` it would
293
- /// yield up:
294
- ///
295
- /// ```notrust
296
- /// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ...
297
- /// ```
298
- fn iter ( & self ) -> PlaceComponentsIter < ' _ , ' tcx > {
299
- PlaceComponentsIter { value : Some ( self ) }
300
- }
301
- }
302
-
303
- /// Iterator over components; see `PlaceComponents::iter` for more
304
- /// information.
305
- ///
306
- /// N.B., this is not a *true* Rust iterator -- the code above just
307
- /// manually invokes `next`. This is because we (sometimes) want to
308
- /// keep executing even after `None` has been returned.
309
- struct PlaceComponentsIter < ' p , ' tcx : ' p > {
310
- value : Option < & ' p PlaceComponents < ' p , ' tcx > > ,
311
- }
312
-
313
- impl < ' p , ' tcx > PlaceComponentsIter < ' p , ' tcx > {
314
- fn next ( & mut self ) -> Option < & ' p Place < ' tcx > > {
315
- if let Some ( & PlaceComponents { component, next } ) = self . value {
316
- self . value = next;
317
- Some ( component)
318
- } else {
319
- None
320
- }
321
- }
322
- }
323
-
324
- /// Recursively "unroll" a place into a `PlaceComponents` list,
325
- /// invoking `op` with a `PlaceComponentsIter`.
326
- fn unroll_place < ' tcx , R > (
327
- place : & Place < ' tcx > ,
328
- next : Option < & PlaceComponents < ' _ , ' tcx > > ,
329
- op : impl FnOnce ( PlaceComponentsIter < ' _ , ' tcx > ) -> R ,
330
- ) -> R {
331
- match place {
332
- Place :: Projection ( interior) => unroll_place (
333
- & interior. base ,
334
- Some ( & PlaceComponents {
335
- component : place,
336
- next,
337
- } ) ,
338
- op,
339
- ) ,
340
-
341
- Place :: Base ( PlaceBase :: Promoted ( _) ) |
342
- Place :: Base ( PlaceBase :: Local ( _) ) | Place :: Base ( PlaceBase :: Static ( _) ) => {
343
- let list = PlaceComponents {
344
- component : place,
345
- next,
346
- } ;
347
- op ( list. iter ( ) )
348
- }
349
- }
350
- }
351
-
352
277
// Given that the bases of `elem1` and `elem2` are always either equal
353
278
// or disjoint (and have the same type!), return the overlap situation
354
279
// between `elem1` and `elem2`.
0 commit comments