Add a lint pass to check for while true { ... } loops
And suggest changing them to loop { ... }. Had to fix the few remaining while true loops (in core::io). Closes #1962.
This commit is contained in:
parent
594d22e7e2
commit
cdc8722f95
@ -110,7 +110,7 @@ impl reader_util for reader {
|
||||
|
||||
fn read_line() -> str {
|
||||
let mut buf: [u8] = [];
|
||||
while true {
|
||||
loop {
|
||||
let ch = self.read_byte();
|
||||
if ch == -1 || ch == 10 { break; }
|
||||
buf += [ch as u8];
|
||||
@ -120,7 +120,7 @@ impl reader_util for reader {
|
||||
|
||||
fn read_c_str() -> str {
|
||||
let mut buf: [u8] = [];
|
||||
while true {
|
||||
loop {
|
||||
let ch = self.read_byte();
|
||||
if ch < 1 { break; } else { buf += [ch as u8]; }
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import syntax::attr;
|
||||
import syntax::codemap::span;
|
||||
import std::map::{map,hashmap,hash_from_strs};
|
||||
import io::writer_util;
|
||||
import syntax::print::pprust::expr_to_str;
|
||||
|
||||
export lint, ctypes, unused_imports;
|
||||
export level, ignore, warn, error;
|
||||
@ -12,17 +13,18 @@ export lookup_lint, lint_dict, get_lint_dict, check_crate;
|
||||
|
||||
#[doc="
|
||||
|
||||
A 'lint' check is a kind of miscallaneous constraint that a user _might_ want
|
||||
A 'lint' check is a kind of miscellaneous constraint that a user _might_ want
|
||||
to enforce, but might reasonably want to permit as well, on a module-by-module
|
||||
basis. They contrast with static constraints enforced by other phases of the
|
||||
compiler, which are generally required to hold in order to compile the program
|
||||
correctly at all.
|
||||
at all.
|
||||
|
||||
"]
|
||||
|
||||
enum lint {
|
||||
ctypes,
|
||||
unused_imports,
|
||||
while_true
|
||||
}
|
||||
|
||||
enum level {
|
||||
@ -35,6 +37,10 @@ type lint_spec = @{lint: lint,
|
||||
|
||||
type lint_dict = hashmap<str,lint_spec>;
|
||||
|
||||
/*
|
||||
Pass names should not contain a '-', as the compiler normalizes
|
||||
'-' to '_' in command-line flags
|
||||
*/
|
||||
fn get_lint_dict() -> lint_dict {
|
||||
let v = [
|
||||
("ctypes",
|
||||
@ -45,7 +51,12 @@ fn get_lint_dict() -> lint_dict {
|
||||
("unused_imports",
|
||||
@{lint: unused_imports,
|
||||
desc: "imports that are never used",
|
||||
default: ignore})
|
||||
default: ignore}),
|
||||
|
||||
("while_true",
|
||||
@{lint: while_true,
|
||||
desc: "suggest using loop { } instead of while(true) { }",
|
||||
default: warn})
|
||||
];
|
||||
hash_from_strs(v)
|
||||
}
|
||||
@ -165,11 +176,34 @@ fn check_item(cx: ctxt, i: @ast::item) {
|
||||
alt lint {
|
||||
ctypes { check_item_ctypes(cx, level, i); }
|
||||
unused_imports { check_item_unused_imports(cx, level, i); }
|
||||
while_true { check_item_while_true(cx, level, i); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_while_true(cx: ctxt, level: level, it: @ast::item) {
|
||||
let visit = visit::mk_simple_visitor(@{
|
||||
visit_expr: fn@(e: @ast::expr) {
|
||||
alt e.node {
|
||||
ast::expr_while(cond, _) {
|
||||
alt cond.node {
|
||||
ast::expr_lit(@{node: ast::lit_bool(true),_}) {
|
||||
cx.span_lint(
|
||||
level, e.span,
|
||||
"Denote infinite loops with loop { ... }");
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
with *visit::default_simple_visitor()
|
||||
});
|
||||
visit::visit_item(it, (), visit);
|
||||
}
|
||||
|
||||
fn check_item_unused_imports(_cx: ctxt, _level: level, _it: @ast::item) {
|
||||
// FIXME: Don't know how to check this in lint yet, it's currently being
|
||||
// done over in resolve. When resolve is rewritten, do it here instead.
|
||||
|
8
src/test/compile-fail/issue-1962.rs
Normal file
8
src/test/compile-fail/issue-1962.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// compile-flags: -W err-while-true
|
||||
fn main() {
|
||||
let mut i = 0;
|
||||
while true { //! ERROR Denote infinite loops with loop
|
||||
i += 1;
|
||||
if i == 5 { break; }
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user