Change:
As per comment before
I don't think this is backwards incompatible.
just a bug, removing milestone/nomination.

Discussion:
// option. This file may not be copied, modified, or distributed // except according to those terms. use middle::ty; <del> use syntax::ast::*; use syntax::visit; </del> <ins> use syntax::ast; use syntax::codemap::Span; </ins> use syntax::visit::Visitor; <ins> use syntax::visit; </ins> <del> #[deriving(Clone)] pub struct Context { in_loop: bool, can_ret: bool </del> <ins> #[deriving(Clone, Eq)] enum Context { Normal, Loop, Closure </ins> } struct CheckLoopVisitor { tcx: ty::ctxt, } <del> pub fn check_crate(tcx: ty::ctxt, crate: &Crate) { visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx }, crate, Context { in_loop: false, can_ret: true }); </del> <ins> pub fn check_crate(tcx: ty::ctxt, crate: &ast::Crate) { visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx }, crate, Normal) </ins> } impl Visitor<Context> for CheckLoopVisitor { <del> fn visit_item(&mut self, i:@item, _cx:Context) { visit::walk_item(self, i, Context { in_loop: false, can_ret: true }); </del> <ins> fn visit_item(&mut self, i: @ast::item, _cx: Context) { visit::walk_item(self, i, Normal); </ins> } <del> fn visit_expr(&mut self, e:@Expr, cx:Context) { match e.node { ExprWhile(e, ref b) => { </del> <ins> fn visit_expr(&mut self, e: @ast::Expr, cx:Context) { match e.node { ast::ExprWhile(e, ref b) => { </ins> self.visit_expr(e, cx); <del> self.visit_block(b, Context { in_loop: true,.. cx }); } ExprLoop(ref b, _) => { self.visit_block(b, Context { in_loop: true,.. cx }); } ExprFnBlock(_, ref b) | ExprProc(_, ref b) => { self.visit_block(b, Context { in_loop: false, can_ret: false }); } ExprBreak(_) => { if !cx.in_loop { self.tcx.sess.span_err(e.span, "`break` outside of loop"); } } ExprAgain(_) => { if !cx.in_loop { self.tcx.sess.span_err(e.span, "`loop` outside of loop"); } } ExprRet(oe) => { if !cx.can_ret { self.tcx.sess.span_err(e.span, "`return` in block function"); </del> <ins> self.visit_block(b, Loop); } ast::ExprLoop(ref b, _) => { self.visit_block(b, Loop); } ast::ExprFnBlock(_, ref b) | ast::ExprProc(_, ref b) => { self.visit_block(b, Closure); } ast::ExprBreak(_) => self.require_loop("break", cx, e.span), ast::ExprAgain(_) => self.require_loop("continue", cx, e.span), ast::ExprRet(oe) => { if cx == Closure { self.tcx.sess.span_err(e.span, "`return` in a closure"); </ins> } visit::walk_expr_opt(self, oe, cx); <del> } _ => visit::walk_expr(self, e, cx) </del> } <ins> _ => visit::walk_expr(self, e, cx) } } } impl CheckLoopVisitor { fn require_loop(&self, name: &str, cx: Context, span: Span) { match cx { Loop => {} Closure => { self.tcx.sess.span_err(span, format!("`{}` inside of a closure", name)); } Normal => { self.tcx.sess.span_err(span, format!("`{}` outside of loop", name)); } } </ins> } }

// option. This file may not be copied, modified, or distributed // except according to those terms. <del> // error-pattern:`break` outside of loop </del> struct Foo { t: ~str } <ins> fn cond() -> bool { true } fn foo(_: ||) {} </ins> fn main() { <del> let pth = break; </del> <ins> let pth = break; //~ ERROR: `break` outside of loop if cond() { continue } //~ ERROR: `continue` outside of loop </ins> <del> let rs: Foo = Foo{t: pth}; </del> <ins> while cond() { if cond() { break } if cond() { continue } do foo { if cond() { break } //~ ERROR: `break` inside of a closure if cond() { continue } //~ ERROR: `continue` inside of a closure } } let rs: Foo = Foo{t: pth}; </ins> }

fn main() { let _x = || { <del> return //~ ERROR: `return` in block function </del> <ins> return //~ ERROR: `return` in a closure </ins> }; }