@@ -2,7 +2,9 @@ use crate::borrow_check::ArtificialField;
22use crate :: borrow_check:: Overlap ;
33use crate :: borrow_check:: { Deep , Shallow , AccessDepth } ;
44use 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+ } ;
68use rustc:: ty:: { self , TyCtxt } ;
79use std:: cmp:: max;
810
@@ -65,8 +67,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
6567 }
6668 }
6769
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| {
7072 place_components_conflict (
7173 tcx,
7274 mir,
@@ -272,83 +274,6 @@ fn place_components_conflict<'gcx, 'tcx>(
272274 }
273275}
274276
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-
352277// Given that the bases of `elem1` and `elem2` are always either equal
353278// or disjoint (and have the same type!), return the overlap situation
354279// between `elem1` and `elem2`.
0 commit comments