summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2019-02-26 23:41:38 +0100
committerSantiago Pastorino <spastorino@gmail.com>2019-03-01 02:40:33 +0100
commit18bc304e5eace68a2ec269832a824130b53b00d6 (patch)
treedd002c8d2f204db9f88ae602919de2c7aa03f662
parentc3171ea059775e951cb07410b93206ed2463792d (diff)
downloadrust-18bc304e5eace68a2ec269832a824130b53b00d6.tar.gz
Move unroll_place to Place::unroll
-rw-r--r--src/librustc/mir/mod.rs76
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs85
2 files changed, 81 insertions, 80 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index b6f5ff25c8f..c01070b3b5a 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2044,6 +2044,82 @@ impl<'tcx> Place<'tcx> {
Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
}
}
+
+ /// Recursively "unroll" a place into a `PlaceComponents` list,
+ /// invoking `op` with a `PlaceComponentsIter`.
+ pub fn unroll<R>(
+ &self,
+ next: Option<&PlaceComponents<'_, 'tcx>>,
+ op: impl FnOnce(PlaceComponentsIter<'_, 'tcx>) -> R,
+ ) -> R {
+ match self {
+ Place::Projection(interior) => interior.base.unroll(
+ Some(&PlaceComponents {
+ component: self,
+ next,
+ }),
+ op,
+ ),
+
+ Place::Base(PlaceBase::Promoted(_)) |
+ Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
+ let list = PlaceComponents {
+ component: self,
+ next,
+ };
+ op(list.iter())
+ }
+ }
+ }
+}
+
+/// A linked list of places running up the stack; begins with the
+/// innermost place and extends to projections (e.g., `a.b` would have
+/// the place `a` with a "next" pointer to `a.b`). Created by
+/// `Place::unroll`.
+///
+/// N.B., this particular impl strategy is not the most obvious. It was
+/// chosen because it makes a measurable difference to NLL
+/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
+pub struct PlaceComponents<'p, 'tcx: 'p> {
+ pub component: &'p Place<'tcx>,
+ pub next: Option<&'p PlaceComponents<'p, 'tcx>>,
+}
+
+impl<'p, 'tcx> PlaceComponents<'p, 'tcx> {
+ /// Converts a list of `Place` components into an iterator; this
+ /// iterator yields up a never-ending stream of `Option<&Place>`.
+ /// These begin with the "innermost" place and then with each
+ /// projection therefrom. So given a place like `a.b.c` it would
+ /// yield up:
+ ///
+ /// ```notrust
+ /// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ...
+ /// ```
+ fn iter(&self) -> PlaceComponentsIter<'_, 'tcx> {
+ PlaceComponentsIter { value: Some(self) }
+ }
+}
+
+/// Iterator over components; see `PlaceComponents::iter` for more
+/// information.
+///
+/// N.B., this is not a *true* Rust iterator -- the code above just
+/// manually invokes `next`. This is because we (sometimes) want to
+/// keep executing even after `None` has been returned.
+pub struct PlaceComponentsIter<'p, 'tcx: 'p> {
+ pub value: Option<&'p PlaceComponents<'p, 'tcx>>,
+}
+
+impl<'p, 'tcx> PlaceComponentsIter<'p, 'tcx> {
+ pub fn next(&mut self) -> Option<&'p Place<'tcx>> {
+ if let Some(&PlaceComponents { component, next }) = self.value {
+ self.value = next;
+ Some(component)
+ } else {
+ None
+ }
+ }
}
impl<'tcx> Debug for Place<'tcx> {
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 1d18ada1fb6..a08da2da777 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -2,7 +2,9 @@ use crate::borrow_check::ArtificialField;
use crate::borrow_check::Overlap;
use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
-use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
+use rustc::mir::{
+ BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, PlaceComponentsIter
+};
use rustc::ty::{self, TyCtxt};
use std::cmp::max;
@@ -65,8 +67,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
}
}
- unroll_place(borrow_place, None, |borrow_components| {
- unroll_place(access_place, None, |access_components| {
+ borrow_place.unroll(None, |borrow_components| {
+ access_place.unroll(None, |access_components| {
place_components_conflict(
tcx,
mir,
@@ -272,83 +274,6 @@ fn place_components_conflict<'gcx, 'tcx>(
}
}
-/// A linked list of places running up the stack; begins with the
-/// innermost place and extends to projections (e.g., `a.b` would have
-/// the place `a` with a "next" pointer to `a.b`). Created by
-/// `unroll_place`.
-///
-/// N.B., this particular impl strategy is not the most obvious. It was
-/// chosen because it makes a measurable difference to NLL
-/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
-struct PlaceComponents<'p, 'tcx: 'p> {
- component: &'p Place<'tcx>,
- next: Option<&'p PlaceComponents<'p, 'tcx>>,
-}
-
-impl<'p, 'tcx> PlaceComponents<'p, 'tcx> {
- /// Converts a list of `Place` components into an iterator; this
- /// iterator yields up a never-ending stream of `Option<&Place>`.
- /// These begin with the "innermost" place and then with each
- /// projection therefrom. So given a place like `a.b.c` it would
- /// yield up:
- ///
- /// ```notrust
- /// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ...
- /// ```
- fn iter(&self) -> PlaceComponentsIter<'_, 'tcx> {
- PlaceComponentsIter { value: Some(self) }
- }
-}
-
-/// Iterator over components; see `PlaceComponents::iter` for more
-/// information.
-///
-/// N.B., this is not a *true* Rust iterator -- the code above just
-/// manually invokes `next`. This is because we (sometimes) want to
-/// keep executing even after `None` has been returned.
-struct PlaceComponentsIter<'p, 'tcx: 'p> {
- value: Option<&'p PlaceComponents<'p, 'tcx>>,
-}
-
-impl<'p, 'tcx> PlaceComponentsIter<'p, 'tcx> {
- fn next(&mut self) -> Option<&'p Place<'tcx>> {
- if let Some(&PlaceComponents { component, next }) = self.value {
- self.value = next;
- Some(component)
- } else {
- None
- }
- }
-}
-
-/// Recursively "unroll" a place into a `PlaceComponents` list,
-/// invoking `op` with a `PlaceComponentsIter`.
-fn unroll_place<'tcx, R>(
- place: &Place<'tcx>,
- next: Option<&PlaceComponents<'_, 'tcx>>,
- op: impl FnOnce(PlaceComponentsIter<'_, 'tcx>) -> R,
-) -> R {
- match place {
- Place::Projection(interior) => unroll_place(
- &interior.base,
- Some(&PlaceComponents {
- component: place,
- next,
- }),
- op,
- ),
-
- Place::Base(PlaceBase::Promoted(_)) |
- Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
- let list = PlaceComponents {
- component: place,
- next,
- };
- op(list.iter())
- }
- }
-}
-
// Given that the bases of `elem1` and `elem2` are always either equal
// or disjoint (and have the same type!), return the overlap situation
// between `elem1` and `elem2`.