Account for labels when suggesting `loop` instead of `while true`

This commit is contained in:
Esteban Küber 2021-01-19 15:51:51 -08:00
parent dc1eee2f25
commit 707ce2b798
7 changed files with 116 additions and 12 deletions

View File

@ -96,18 +96,24 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
impl EarlyLintPass for WhileTrue {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
if let ast::ExprKind::While(cond, ..) = &e.kind {
if let ast::ExprKind::While(cond, _, label) = &e.kind {
if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
if let ast::LitKind::Bool(true) = lit.kind {
if !lit.span.from_expansion() {
let msg = "denote infinite loops with `loop { ... }`";
let condition_span = cx.sess.source_map().guess_head_span(e.span);
let condition_span = e.span.with_hi(cond.span.hi());
cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
lint.build(msg)
.span_suggestion_short(
condition_span,
"use `loop`",
"loop".to_owned(),
format!(
"{}loop",
label.map_or_else(String::new, |label| format!(
"{}: ",
label.ident,
))
),
Applicability::MachineApplicable,
)
.emit();

View File

@ -3,8 +3,8 @@
fn main() {
let mut i = 0;
loop { //~ ERROR denote infinite loops with `loop
'a: loop { //~ ERROR denote infinite loops with `loop
i += 1;
if i == 5 { break; }
if i == 5 { break 'a; }
}
}

View File

@ -3,8 +3,8 @@
fn main() {
let mut i = 0;
while true { //~ ERROR denote infinite loops with `loop
'a: while true { //~ ERROR denote infinite loops with `loop
i += 1;
if i == 5 { break; }
if i == 5 { break 'a; }
}
}

View File

@ -1,8 +1,8 @@
error: denote infinite loops with `loop { ... }`
--> $DIR/issue-1962.rs:6:5
|
LL | while true {
| ^^^^^^^^^^ help: use `loop`
LL | 'a: while true {
| ^^^^^^^^^^^^^^ help: use `loop`
|
= note: requested on the command line with `-D while-true`

View File

@ -4,7 +4,7 @@ warning: denote infinite loops with `loop { ... }`
LL | / 'b:
LL | |
LL | | while true { break }; // but here we cite the whole loop
| |____________________________^ help: use `loop`
| |__________________^ help: use `loop`
|
= note: `#[warn(while_true)]` on by default

View File

@ -16,3 +16,25 @@ fn main() {
//~^ ERROR cannot find value `for_loop` in this scope
};
}
fn foo() {
'LOOP: loop {
break LOOP;
//~^ ERROR cannot find value `LOOP` in this scope
};
'while_loop: while true { //~ WARN denote infinite loops with
break while_loop;
//~^ ERROR cannot find value `while_loop` in this scope
//~| ERROR `break` with value from a `while` loop
};
'while_let: while let Some(_) = Some(()) {
break while_let;
//~^ ERROR cannot find value `while_let` in this scope
//~| ERROR `break` with value from a `while` loop
}
'for_loop: for _ in 0..3 {
break for_loop;
//~^ ERROR cannot find value `for_loop` in this scope
//~| ERROR `break` with value from a `for` loop
};
}

View File

@ -34,6 +34,42 @@ LL | for_loop;
| not found in this scope
| help: a label with a similar name exists: `'for_loop`
error[E0425]: cannot find value `LOOP` in this scope
--> $DIR/label_misspelled.rs:22:15
|
LL | break LOOP;
| ^^^^
| |
| not found in this scope
| help: a label with a similar name exists: `'LOOP`
error[E0425]: cannot find value `while_loop` in this scope
--> $DIR/label_misspelled.rs:26:15
|
LL | break while_loop;
| ^^^^^^^^^^
| |
| not found in this scope
| help: a label with a similar name exists: `'while_loop`
error[E0425]: cannot find value `while_let` in this scope
--> $DIR/label_misspelled.rs:31:15
|
LL | break while_let;
| ^^^^^^^^^
| |
| not found in this scope
| help: a label with a similar name exists: `'while_let`
error[E0425]: cannot find value `for_loop` in this scope
--> $DIR/label_misspelled.rs:36:15
|
LL | break for_loop;
| ^^^^^^^^
| |
| not found in this scope
| help: a label with a similar name exists: `'for_loop`
warning: denote infinite loops with `loop { ... }`
--> $DIR/label_misspelled.rs:6:5
|
@ -42,6 +78,46 @@ LL | 'while_loop: while true {
|
= note: `#[warn(while_true)]` on by default
error: aborting due to 4 previous errors; 1 warning emitted
warning: denote infinite loops with `loop { ... }`
--> $DIR/label_misspelled.rs:25:5
|
LL | 'while_loop: while true {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop`
For more information about this error, try `rustc --explain E0425`.
error[E0571]: `break` with value from a `while` loop
--> $DIR/label_misspelled.rs:26:9
|
LL | break while_loop;
| ^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
|
help: instead, use `break` on its own without a value inside this `while` loop
|
LL | break;
| ^^^^^
error[E0571]: `break` with value from a `while` loop
--> $DIR/label_misspelled.rs:31:9
|
LL | break while_let;
| ^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
|
help: instead, use `break` on its own without a value inside this `while` loop
|
LL | break;
| ^^^^^
error[E0571]: `break` with value from a `for` loop
--> $DIR/label_misspelled.rs:36:9
|
LL | break for_loop;
| ^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
|
help: instead, use `break` on its own without a value inside this `for` loop
|
LL | break;
| ^^^^^
error: aborting due to 11 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0425, E0571.
For more information about an error, try `rustc --explain E0425`.