From 497273620bc019bedc1c47ff541e768a4176beff Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 27 Jun 2018 12:58:29 -0400 Subject: [PATCH] don't use Iterator and zip but just invoke `next` manually This micro-optimizes some if checks away; the compiler may already have been doing it, not sure. --- .../borrow_check/places_conflict.rs | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 87126bc453a..8fe4282d90c 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -38,8 +38,8 @@ pub(super) fn places_conflict<'gcx, 'tcx>( fn place_components_conflict<'gcx, 'tcx>( tcx: TyCtxt<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - borrow_components: PlaceComponentsIter<'_, 'tcx>, - access_components: PlaceComponentsIter<'_, 'tcx>, + mut borrow_components: PlaceComponentsIter<'_, 'tcx>, + mut access_components: PlaceComponentsIter<'_, 'tcx>, access: ShallowOrDeep, ) -> bool { // The borrowck rules for proving disjointness are applied from the "root" of the @@ -83,11 +83,14 @@ fn place_components_conflict<'gcx, 'tcx>( // - If we didn't run out of access to match, our borrow and access are comparable // and either equal or disjoint. // - If we did run out of accesss, the borrow can access a part of it. - for (borrow_c, access_c) in borrow_components.zip(access_components) { + loop { // loop invariant: borrow_c is always either equal to access_c or disjoint from it. - debug!("places_conflict: {:?} vs. {:?}", borrow_c, access_c); - if let Some(borrow_c) = borrow_c { - if let Some(access_c) = access_c { + if let Some(borrow_c) = borrow_components.next() { + debug!("places_conflict: borrow_c = {:?}", borrow_c); + + if let Some(access_c) = access_components.next() { + debug!("places_conflict: access_c = {:?}", access_c); + // Borrow and access path both have more components. // // Examples: @@ -214,7 +217,6 @@ fn place_components_conflict<'gcx, 'tcx>( return true; } } - unreachable!("iter::repeat returned None") } /// A linked list of places running up the stack; begins with the @@ -243,19 +245,21 @@ impl<'p, 'tcx> PlaceComponents<'p, 'tcx> { /// Iterator over components; see `PlaceComponents::iter` for more /// information. +/// +/// NB: 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> Iterator for PlaceComponentsIter<'p, 'tcx> { - type Item = Option<&'p Place<'tcx>>; - - fn next(&mut self) -> Option { +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(Some(component)) + Some(component) } else { - Some(None) + None } } }