Change:
MIR borrowck considers variables still initialized after their storage ends, so if an immutable variable is defined and used in a loop, this causes an error. e.g.: Which causes:
working on it

Discussion:
// option. This file may not be copied, modified, or distributed // except according to those terms. <del> use syntax_pos::DUMMY_SP; </del> use rustc::mir::{self, Mir, Location}; use rustc::ty::{self, TyCtxt}; use util::elaborate_drops::DropFlagState;

where F: FnMut(MovePathIndex, DropFlagState) { let move_data = &ctxt.move_data; <del> let param_env = ctxt.param_env; </del> debug!("drop_flag_effects_for_location({:?})", loc); // first, move out of the RHS

let path = mi.move_path_index(move_data); debug!("moving out of path {:?}", move_data.move_paths[path]); <del> // don't move out of non-Copy things let lvalue = &move_data.move_paths[path].lvalue; let ty = lvalue.ty(mir, tcx).to_ty(tcx); let gcx = tcx.global_tcx(); let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap(); if !erased_ty.moves_by_default(gcx, param_env, DUMMY_SP) { continue; } </del> on_all_children_bits(tcx, mir, move_data, path, |mpi| callback(mpi, DropFlagState::Absent))

let path_map = &move_data.path_map; let rev_lookup = &move_data.rev_lookup; <del> debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", stmt, location, &loc_map[location]); for move_index in &loc_map[location] { // Every path deinitialized by a *particular move* // has corresponding bit, "gen'ed" (i.e. set) // here, in dataflow vector zero_to_one(sets.gen_set.words_mut(), *move_index); </del> <ins> match stmt.kind { // this analysis only tries to find moves explicitly // written by the user, so we ignore the move-outs // created by `StorageDead` and at the beginning // of a function. mir::StatementKind::StorageDead(_) => {} _ => { debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", stmt, location, &loc_map[location]); for move_index in &loc_map[location] { // Every path deinitialized by a *particular move* // has corresponding bit, "gen'ed" (i.e. set) // here, in dataflow vector zero_to_one(sets.gen_set.words_mut(), *move_index); } } </ins> } let bits_per_block = self.bits_per_block(); match stmt.kind { mir::StatementKind::SetDiscriminant { .. } => {

} self.gather_rvalue(rval); } <del> StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => {} </del> <ins> StatementKind::StorageLive(_) => {} StatementKind::StorageDead(local) => { self.gather_move(&Lvalue::Local(local), true); } </ins> StatementKind::SetDiscriminant{ .. } => { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist during borrowck");

TerminatorKind::Unreachable => { } TerminatorKind::Return => { <del> self.gather_move(&Lvalue::Local(RETURN_POINTER)); </del> <ins> self.gather_move(&Lvalue::Local(RETURN_POINTER), false); </ins> } TerminatorKind::Assert { .. } |

} TerminatorKind::Drop { ref location, target: _, unwind: _ } => { <del> self.gather_move(location); </del> <ins> self.gather_move(location, false); </ins> } TerminatorKind::DropAndReplace { ref location, ref value, .. } => { self.create_move_path(location);

match *operand { Operand::Constant(..) => {} // not-a-move Operand::Consume(ref lval) => { // a move <del> self.gather_move(lval); </del> <ins> self.gather_move(lval, false); </ins> } } } <del> fn gather_move(&mut self, lval: &Lvalue<'tcx>) { </del> <ins> fn gather_move(&mut self, lval: &Lvalue<'tcx>, force: bool) { </ins> debug!("gather_move({:?}, {:?})", self.loc, lval); let tcx = self.builder.tcx; let gcx = tcx.global_tcx(); let lv_ty = lval.ty(self.builder.mir, tcx).to_ty(tcx); let erased_ty = gcx.lift(&tcx.erase_regions(&lv_ty)).unwrap(); <del> if !erased_ty.moves_by_default(gcx, self.builder.param_env, DUMMY_SP) { </del> <ins> if !force && !erased_ty.moves_by_default(gcx, self.builder.param_env, DUMMY_SP) { </ins> debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", self.loc, lval, lv_ty); return }

<ins> // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // compile-flags: -Z emit-end-regions -Z borrowck-mir fn ok() { loop { let _x = 1; } } fn fail() { loop { let x: i32; let _ = x + 1; //~ERROR (Ast) [E0381] //~^ ERROR (Mir) [E0381] } } fn main() { ok(); fail(); } </ins>

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