Change:
MIR borrowck ICEs when an error involving a region whose EndRegion is missing occurs (this occurs when a region can never end within the function). Instead it should emit a correct diagnostic. This can occur for both free regions (e.g. issue-): And for infinite loops: Causing this ICE:
The ICE here is caused by the assert in this function, : This function finds the (location in the input source code) that a region ends. If you look at the error that the AST borrowck (i.e., older style borrowck) emits, we are basically computing the point where to write that "immutable borrow ends here" message: Right now, there is a kind of complicated assertion. It is saying that one of two things should be: We are in non-lexical mode. In that case, there are no end-regions at all, so we just return . This causes us not to write "immutable borrow ends here". We are in lexical mode, in which case we should have found an statement. These are special statements we insert into the MIR (only in lexical mode) that tell us where the various lexical lifetimes end. The problem is that in cases where the region never properly ends, we won't find an statement. I think what we want to do is rewrite the function a bit. If we are in NLL mode (), then we should always return . Otherwise, check the as we are doing and return if we find something in there, as we are doing now. Otherwise, we want to return the span for the end of the function. This is the new part. As it happens, we can get this by returning : is the MIR for the function we are checking is the span in the source code where the function is defined returning its end point should, I think, give us the behavior we want. So, when we are done, if is , this function should always return for some span, but sometimes it will be the end of the function.
Hi, I want to work on this bug.

Discussion:
/// Returns the span for the "end point" given region. This will /// return `None` if NLL is enabled, since that concept has no <del> /// meaning there.  Otherwise, it should return some. </del> <ins> /// meaning there.  Otherwise, return region span if it exists and /// span for end of the function if it doesn't exist. </ins> pub fn opt_region_end_span(&self, region: &Region) -> Option<Span> { <del> let opt_span = self.region_span_map.get(region); assert!(self.nonlexical_regioncx.is_some() || opt_span.is_some(), "end region not found for {:?}", region); opt_span.map(|s| s.end_point()) </del> <ins> match self.nonlexical_regioncx { Some(_) => None, None => { match self.region_span_map.get(region) { Some(span) => Some(span.end_point()), None => Some(self.mir.span.end_point()) } } } </ins> } /// Add all borrows to the kill set, if those borrows are out of scope at `location`.

// conflicts with a new loan, as opposed to every issued loan.  This keeps us // down to O(n) errors (for n problem lines), instead of O(n^2) errors. <ins> // revisions: ast mir //[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir </ins> fn main() { let mut x = 1; let mut addr; loop { match 1 { <del> 1 => { addr = &mut x; } //~^ ERROR cannot borrow `x` as mutable more than once at a time 2 => { addr = &mut x; } //~^ ERROR cannot borrow `x` as mutable more than once at a time _ => { addr = &mut x; } //~^ ERROR cannot borrow `x` as mutable more than once at a time </del> <ins> 1 => { addr = &mut x; } //[ast]~ ERROR [E0499] //[mir]~^ ERROR (Ast) [E0499] //[mir]~| ERROR (Mir) [E0499] 2 => { addr = &mut x; } //[ast]~ ERROR [E0499] //[mir]~^ ERROR (Ast) [E0499] //[mir]~| ERROR (Mir) [E0506] //[mir]~| ERROR (Mir) [E0499] //[mir]~| ERROR (Mir) [E0499] _ => { addr = &mut x; } //[ast]~ ERROR [E0499] //[mir]~^ ERROR (Ast) [E0499] //[mir]~| ERROR (Mir) [E0506] //[mir]~| ERROR (Mir) [E0499] //[mir]~| ERROR (Mir) [E0499] </ins> } } }

// option. This file may not be copied, modified, or distributed // except according to those terms. <ins> // revisions: ast mir //[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir </ins> enum Sexpression { Num(()), Cons(&'static mut Sexpression)

fn causes_ice(mut l: &mut Sexpression) { loop { match l { <del> &mut Sexpression::Num(ref mut n) => {}, &mut Sexpression::Cons(ref mut expr) => { //~ ERROR cannot borrow `l.0` l = &mut **expr; //~ ERROR cannot assign to `l` </del> <ins> &mut Sexpression::Num(ref mut n) => {}, //[mir]~ ERROR (Mir) [E0384] &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499] //[mir]~^ ERROR (Ast) [E0499] //[mir]~| ERROR (Mir) [E0506] //[mir]~| ERROR (Mir) [E0384] //[mir]~| ERROR (Mir) [E0499] l = &mut **expr; //[ast]~ ERROR [E0506] //[mir]~^ ERROR (Ast) [E0506] //[mir]~| ERROR (Mir) [E0506] //[mir]~| ERROR (Mir) [E0506] //[mir]~| ERROR (Mir) [E0499] //[mir]~| ERROR (Mir) [E0499] </ins> } }} }