diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index a6aab151e5ad9..8a320f88649a0 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -8,68 +8,68 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use middle::ty; -use syntax::ast::*; -use syntax::visit; +use syntax::ast; +use syntax::codemap::Span; use syntax::visit::Visitor; +use syntax::visit; -#[deriving(Clone)] -pub struct Context { - in_loop: bool, - can_ret: bool +#[deriving(Clone, Eq)] +enum Context { + Normal, Loop, Closure } struct CheckLoopVisitor { tcx: ty::ctxt, } -pub fn check_crate(tcx: ty::ctxt, crate: &Crate) { - visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx }, - crate, - Context { in_loop: false, can_ret: true }); +pub fn check_crate(tcx: ty::ctxt, crate: &ast::Crate) { + visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx }, crate, Normal) } impl Visitor for CheckLoopVisitor { - fn visit_item(&mut self, i:@item, _cx:Context) { - visit::walk_item(self, i, Context { - in_loop: false, - can_ret: true - }); + fn visit_item(&mut self, i: @ast::item, _cx: Context) { + visit::walk_item(self, i, Normal); } - fn visit_expr(&mut self, e:@Expr, cx:Context) { - - match e.node { - ExprWhile(e, ref b) => { + fn visit_expr(&mut self, e: @ast::Expr, cx:Context) { + match e.node { + ast::ExprWhile(e, ref b) => { self.visit_expr(e, cx); - 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"); + 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"); } visit::walk_expr_opt(self, oe, cx); - } - _ => visit::walk_expr(self, e, cx) } + _ => 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)); + } + } } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 23fef5e351674..4861fa19f7e8f 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -25,7 +25,6 @@ use syntax::ast::*; use syntax::ast; use syntax::ast_util::{def_id_of_def, local_def, mtwt_resolve}; use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method}; -use syntax::attr; use syntax::parse::token; use syntax::parse::token::{ident_interner, interner_get}; use syntax::parse::token::special_idents; @@ -254,19 +253,6 @@ enum MethodSort { Provided(NodeId) } -// The X-ray flag indicates that a context has the X-ray privilege, which -// allows it to reference private names. Currently, this is used for the test -// runner. -// -// FIXME #4947: The X-ray flag is kind of questionable in the first -// place. It might be better to introduce an expr_xray_path instead. - -#[deriving(Eq)] -enum XrayFlag { - NoXray, //< Private items cannot be accessed. - Xray //< Private items can be accessed. -} - enum UseLexicalScopeFlag { DontUseLexicalScope, UseLexicalScope @@ -831,7 +817,6 @@ fn Resolver(session: Session, type_ribs: @mut ~[], label_ribs: @mut ~[], - xray_context: NoXray, current_trait_refs: None, self_ident: special_idents::self_, @@ -883,10 +868,6 @@ struct Resolver { // The current set of local scopes, for labels. label_ribs: @mut ~[@Rib], - // Whether the current context is an X-ray context. An X-ray context is - // allowed to access private names of any module. - xray_context: XrayFlag, - // The trait that the current context can refer to. current_trait_refs: Option<~[DefId]>, @@ -3545,13 +3526,6 @@ impl Resolver { debug!("(resolving item) resolving {}", self.session.str_of(item.ident)); - // Items with the !resolve_unexported attribute are X-ray contexts. - // This is used to allow the test runner to run unexported tests. - let orig_xray_flag = self.xray_context; - if attr::contains_name(item.attrs, "!resolve_unexported") { - self.xray_context = Xray; - } - match item.node { // enum item: resolve all the variants' discrs, @@ -3715,8 +3689,6 @@ impl Resolver { fail!("item macros unimplemented") } } - - self.xray_context = orig_xray_flag; } fn with_type_parameter_rib(&mut self, diff --git a/src/test/compile-fail/break-outside-loop.rs b/src/test/compile-fail/break-outside-loop.rs index b3154c9742aca..06281a5e2884b 100644 --- a/src/test/compile-fail/break-outside-loop.rs +++ b/src/test/compile-fail/break-outside-loop.rs @@ -8,15 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:`break` outside of loop - struct Foo { t: ~str } +fn cond() -> bool { true } + +fn foo(_: ||) {} + fn main() { - let pth = break; + let pth = break; //~ ERROR: `break` outside of loop + if cond() { continue } //~ ERROR: `continue` outside of loop - let rs: Foo = Foo{t: pth}; + 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}; } diff --git a/src/test/compile-fail/return-in-block-function.rs b/src/test/compile-fail/return-in-block-function.rs index 75a72f97204ef..f231810cbf117 100644 --- a/src/test/compile-fail/return-in-block-function.rs +++ b/src/test/compile-fail/return-in-block-function.rs @@ -10,6 +10,6 @@ fn main() { let _x = || { - return //~ ERROR: `return` in block function + return //~ ERROR: `return` in a closure }; }