Skip to content

Commit 7048b08

Browse files
committed
Move unroll_place to Place::unroll
1 parent 17add24 commit 7048b08

File tree

2 files changed

+81
-80
lines changed

2 files changed

+81
-80
lines changed

src/librustc/mir/mod.rs

+76
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,82 @@ impl<'tcx> Place<'tcx> {
20442044
Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
20452045
}
20462046
}
2047+
2048+
/// Recursively "unroll" a place into a `PlaceComponents` list,
2049+
/// invoking `op` with a `PlaceComponentsIter`.
2050+
pub fn unroll<R>(
2051+
&self,
2052+
next: Option<&PlaceComponents<'_, 'tcx>>,
2053+
op: impl FnOnce(PlaceComponentsIter<'_, 'tcx>) -> R,
2054+
) -> R {
2055+
match self {
2056+
Place::Projection(interior) => interior.base.unroll(
2057+
Some(&PlaceComponents {
2058+
component: self,
2059+
next,
2060+
}),
2061+
op,
2062+
),
2063+
2064+
Place::Base(PlaceBase::Promoted(_)) |
2065+
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
2066+
let list = PlaceComponents {
2067+
component: self,
2068+
next,
2069+
};
2070+
op(list.iter())
2071+
}
2072+
}
2073+
}
2074+
}
2075+
2076+
/// A linked list of places running up the stack; begins with the
2077+
/// innermost place and extends to projections (e.g., `a.b` would have
2078+
/// the place `a` with a "next" pointer to `a.b`). Created by
2079+
/// `Place::unroll`.
2080+
///
2081+
/// N.B., this particular impl strategy is not the most obvious. It was
2082+
/// chosen because it makes a measurable difference to NLL
2083+
/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
2084+
pub struct PlaceComponents<'p, 'tcx: 'p> {
2085+
pub component: &'p Place<'tcx>,
2086+
pub next: Option<&'p PlaceComponents<'p, 'tcx>>,
2087+
}
2088+
2089+
impl<'p, 'tcx> PlaceComponents<'p, 'tcx> {
2090+
/// Converts a list of `Place` components into an iterator; this
2091+
/// iterator yields up a never-ending stream of `Option<&Place>`.
2092+
/// These begin with the "innermost" place and then with each
2093+
/// projection therefrom. So given a place like `a.b.c` it would
2094+
/// yield up:
2095+
///
2096+
/// ```notrust
2097+
/// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ...
2098+
/// ```
2099+
fn iter(&self) -> PlaceComponentsIter<'_, 'tcx> {
2100+
PlaceComponentsIter { value: Some(self) }
2101+
}
2102+
}
2103+
2104+
/// Iterator over components; see `PlaceComponents::iter` for more
2105+
/// information.
2106+
///
2107+
/// N.B., this is not a *true* Rust iterator -- the code above just
2108+
/// manually invokes `next`. This is because we (sometimes) want to
2109+
/// keep executing even after `None` has been returned.
2110+
pub struct PlaceComponentsIter<'p, 'tcx: 'p> {
2111+
pub value: Option<&'p PlaceComponents<'p, 'tcx>>,
2112+
}
2113+
2114+
impl<'p, 'tcx> PlaceComponentsIter<'p, 'tcx> {
2115+
pub fn next(&mut self) -> Option<&'p Place<'tcx>> {
2116+
if let Some(&PlaceComponents { component, next }) = self.value {
2117+
self.value = next;
2118+
Some(component)
2119+
} else {
2120+
None
2121+
}
2122+
}
20472123
}
20482124

20492125
impl<'tcx> Debug for Place<'tcx> {

src/librustc_mir/borrow_check/places_conflict.rs

+5-80
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use crate::borrow_check::ArtificialField;
22
use crate::borrow_check::Overlap;
33
use crate::borrow_check::{Deep, Shallow, AccessDepth};
44
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+
};
68
use rustc::ty::{self, TyCtxt};
79
use 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

Comments
 (0)