diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-06-20 18:50:44 -0700 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-06-20 18:53:38 -0700 |
| commit | f331cd9324e4c4246fb3f332720a444042267e69 (patch) | |
| tree | a1d3b6f5484553ec79acffefbfbcbbd97df56476 | |
| parent | 613deb03127d0930e4624d0c0a8744c849093019 (diff) | |
| download | rust-f331cd9324e4c4246fb3f332720a444042267e69.tar.gz rust-f331cd9324e4c4246fb3f332720a444042267e69.zip | |
Don't consider loops to be breaking if they contain inner loops that break
Closes #2642
| -rw-r--r-- | src/rustc/util/common.rs | 26 | ||||
| -rw-r--r-- | src/test/run-pass/issue-2642.rs | 6 |
2 files changed, 23 insertions, 9 deletions
diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index ec599e72c4c..e12aa98b67a 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -34,25 +34,33 @@ fn field_exprs(fields: [ast::field]) -> [@ast::expr] { } // Takes a predicate p, returns true iff p is true for any subexpressions -// of b -fn block_expr_query(b: ast::blk, p: fn@(ast::expr_) -> bool) -> bool { +// of b -- skipping any inner loops (loop, while, loop_body) +fn loop_query(b: ast::blk, p: fn@(ast::expr_) -> bool) -> bool { let rs = @mut false; - let visit_expr = {|flag: @mut bool, e: @ast::expr| *flag |= p(e.node)}; - let v = - visit::mk_simple_visitor(@{visit_expr: {|a|visit_expr(rs, a)} - with *visit::default_simple_visitor()}); - visit::visit_block(b, (), v); + let visit_expr = {|e: @ast::expr, &&flag: @mut bool, + v: visit::vt<@mut bool>| + *flag |= p(e.node); + alt e.node { + // Skip inner loops, since a break in the inner loop isn't a + // break inside the outer loop + ast::expr_loop(*) | ast::expr_while(*) | ast::expr_loop_body(*) {} + _ { visit::visit_expr(e, flag, v); } + } + }; + let v = visit::mk_vt(@{visit_expr: visit_expr + with *visit::default_visitor()}); + visit::visit_block(b, rs, v); ret *rs; } fn has_nonlocal_exits(b: ast::blk) -> bool { - block_expr_query(b) {|e| alt e { + loop_query(b) {|e| alt e { ast::expr_break | ast::expr_cont { true } _ { false }}} } fn may_break(b: ast::blk) -> bool { - block_expr_query(b) {|e| alt e { + loop_query(b) {|e| alt e { ast::expr_break { true } _ { false }}} } diff --git a/src/test/run-pass/issue-2642.rs b/src/test/run-pass/issue-2642.rs new file mode 100644 index 00000000000..63e1fda60a8 --- /dev/null +++ b/src/test/run-pass/issue-2642.rs @@ -0,0 +1,6 @@ +fn f() { + let _x: uint = loop { loop { break; } }; +} + +fn main() { +} |
