Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. --Given the following code: The current output is: It looks like the error is pointing to the wrong spot in the code and is quite misleading. Ideally the output should mention that is still mutably borrowed because it holds a reference to between loops. Or something, im not actually sure :P I have confirmed that this occurs in both the latest stable (1.62.1) and nightly () <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
With the proposed the output will be like this:

Discussion:
//! Print diagnostics to explain why values are borrowed. <del> use std::collections::VecDeque; use rustc_data_structures::fx::FxHashSet; </del> use rustc_errors::{Applicability, Diagnostic}; use rustc_index::vec::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin;

let borrow_region_vid = borrow.region; debug!(?borrow_region_vid); <del> let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location); </del> <ins> let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location); </ins> debug!(?region_sub); <del> match find_use::find(body, regioncx, tcx, region_sub, location) { </del> <ins> let mut use_location = location; let mut use_in_later_iteration_of_loop = false; if region_sub == borrow_region_vid { // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow is // issued is the same location that invalidates the reference), this is likely a loop iteration // - in this case, try using the loop terminator location in `find_sub_region_live_at`. if let Some(loop_terminator_location) = regioncx.find_loop_terminator_location(borrow.region, body) { region_sub = self .regioncx .find_sub_region_live_at(borrow_region_vid, loop_terminator_location); debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub); use_location = loop_terminator_location; use_in_later_iteration_of_loop = true; } } match find_use::find(body, regioncx, tcx, region_sub, use_location) { </ins> Some(Cause::LiveVar(local, location)) => { let span = body.source_info(location).span; let spans = self .move_spans(Place::from(local).as_ref(), location) .or_else(|| self.borrow_spans(span, location)); <del> let borrow_location = location; if self.is_use_in_later_iteration_of_loop(borrow_location, location) { let later_use = self.later_use_kind(borrow, spans, location); </del> <ins> if use_in_later_iteration_of_loop { let later_use = self.later_use_kind(borrow, spans, use_location); </ins> BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2) } else { // Check if the location represents a `FakeRead`, and adapt the error

} } <del> /// true if `borrow_location` can reach `use_location` by going through a loop and /// `use_location` is also inside of that loop fn is_use_in_later_iteration_of_loop( &self, borrow_location: Location, use_location: Location, ) -> bool { let back_edge = self.reach_through_backedge(borrow_location, use_location); back_edge.map_or(false, |back_edge| self.can_reach_head_of_loop(use_location, back_edge)) } /// Returns the outmost back edge if `from` location can reach `to` location passing through /// that back edge fn reach_through_backedge(&self, from: Location, to: Location) -> Option<Location> { let mut visited_locations = FxHashSet::default(); let mut pending_locations = VecDeque::new(); visited_locations.insert(from); pending_locations.push_back(from); debug!("reach_through_backedge: from={:?} to={:?}", from, to,); let mut outmost_back_edge = None; while let Some(location) = pending_locations.pop_front() { debug!( "reach_through_backedge: location={:?} outmost_back_edge={:?} pending_locations={:?} visited_locations={:?}", location, outmost_back_edge, pending_locations, visited_locations ); if location == to && outmost_back_edge.is_some() { // We've managed to reach the use location debug!("reach_through_backedge: found!"); return outmost_back_edge; } let block = &self.body.basic_blocks[location.block]; if location.statement_index < block.statements.len() { let successor = location.successor_within_block(); if visited_locations.insert(successor) { pending_locations.push_back(successor); } } else { pending_locations.extend( block .terminator() .successors() .map(|bb| Location { statement_index: 0, block: bb }) .filter(|s| visited_locations.insert(*s)) .map(|s| { if self.is_back_edge(location, s) { match outmost_back_edge { None => { outmost_back_edge = Some(location); } Some(back_edge) if location.dominates(back_edge, &self.dominators) => { outmost_back_edge = Some(location); } Some(_) => {} } } s }), ); } } None } /// true if `from` location can reach `loop_head` location and `loop_head` dominates all the /// intermediate nodes fn can_reach_head_of_loop(&self, from: Location, loop_head: Location) -> bool { self.find_loop_head_dfs(from, loop_head, &mut FxHashSet::default()) } fn find_loop_head_dfs( &self, from: Location, loop_head: Location, visited_locations: &mut FxHashSet<Location>, ) -> bool { visited_locations.insert(from); if from == loop_head { return true; } if loop_head.dominates(from, &self.dominators) { let block = &self.body.basic_blocks[from.block]; if from.statement_index < block.statements.len() { let successor = from.successor_within_block(); if !visited_locations.contains(&successor) && self.find_loop_head_dfs(successor, loop_head, visited_locations) { return true; } } else { for bb in block.terminator().successors() { let successor = Location { statement_index: 0, block: bb }; if !visited_locations.contains(&successor) && self.find_loop_head_dfs(successor, loop_head, visited_locations) { return true; } } } } false } /// True if an edge `source -> target` is a backedge -- in other words, if the target /// dominates the source. fn is_back_edge(&self, source: Location, target: Location) -> bool { target.dominates(source, &self.dominators) } </del> /// Determine how the borrow was later used. /// First span returned points to the location of the conflicting use /// Second span if `Some` is returned in the case of closures and points

use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_middle::mir::{ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, <del> ConstraintCategory, Local, Location, ReturnConstraint, </del> <ins> ConstraintCategory, Local, Location, ReturnConstraint, TerminatorKind, </ins> }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode;

pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { self.universe_causes[&universe].clone() } <ins> /// Tries to find the terminator of the loop in which the region 'r' resides. /// Returns the location of the terminator if found. pub(crate) fn find_loop_terminator_location( &self, r: RegionVid, body: &Body<'_>, ) -> Option<Location> { let scc = self.constraint_sccs.scc(r.to_region_vid()); let locations = self.scc_values.locations_outlived_by(scc); for location in locations { let bb = &body[location.block]; if let Some(terminator) = &bb.terminator { // terminator of a loop should be TerminatorKind::FalseUnwind if let TerminatorKind::FalseUnwind { .. } = terminator.kind { return Some(location); } } } None } </ins> } impl<'tcx> RegionDefinition<'tcx> {

--> $DIR/borrowck-mut-borrow-linear-errors.rs:12:30 | LL |             _ => { addr.push(&mut x); } <del> |                              ^^^^^^ `x` was mutably borrowed here in the previous iteration of the loop </del> <ins> |                    ----------^^^^^^- |                    |         | |                    |         `x` was mutably borrowed here in the previous iteration of the loop |                    first borrow used here, in later iteration of loop </ins> error: aborting due to 3 previous errors

--> $DIR/two-phase-across-loop.rs:17:22 | LL |         strings.push(foo.get_string()); <del> |                      ^^^^^^^^^^^^^^^^ `foo` was mutably borrowed here in the previous iteration of the loop </del> <ins> |         -------------^^^^^^^^^^^^^^^^- |         |            | |         |            `foo` was mutably borrowed here in the previous iteration of the loop |         first borrow used here, in later iteration of loop </ins> error: aborting due to previous error

--> $DIR/closures-in-loops.rs:13:16 | LL |         v.push(|| x = String::new()); <del> |                ^^ - borrows occur due to use of `x` in closure |                | |                `x` was mutably borrowed here in the previous iteration of the loop </del> <ins> |         -------^^------------------- |         |      |  | |         |      |  borrows occur due to use of `x` in closure |         |      `x` was mutably borrowed here in the previous iteration of the loop |         first borrow used here, in later iteration of loop </ins> error[E0524]: two closures require unique access to `x` at the same time --> $DIR/closures-in-loops.rs:20:16 | LL |         v.push(|| *x = String::new()); <del> |                ^^ -- borrows occur due to use of `x` in closure |                | |                closures are constructed here in different iterations of loop </del> <ins> |         -------^^-------------------- |         |      |  | |         |      |  borrows occur due to use of `x` in closure |         |      closures are constructed here in different iterations of loop |         first borrow used here, in later iteration of loop </ins> error: aborting due to 3 previous errors