From 707ce2b798ad7bb6c1e0fce0da542d9caef07b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 19 Jan 2021 15:51:51 -0800 Subject: [PATCH] Account for labels when suggesting `loop` instead of `while true` --- compiler/rustc_lint/src/builtin.rs | 12 +++- src/test/ui/issues/issue-1962.fixed | 4 +- src/test/ui/issues/issue-1962.rs | 4 +- src/test/ui/issues/issue-1962.stderr | 4 +- src/test/ui/issues/issue-27042.stderr | 2 +- src/test/ui/label/label_misspelled.rs | 22 +++++++ src/test/ui/label/label_misspelled.stderr | 80 ++++++++++++++++++++++- 7 files changed, 116 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8cdb33ea317..b37660e4a90 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -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(); diff --git a/src/test/ui/issues/issue-1962.fixed b/src/test/ui/issues/issue-1962.fixed index b810a90ef37..897fd172b29 100644 --- a/src/test/ui/issues/issue-1962.fixed +++ b/src/test/ui/issues/issue-1962.fixed @@ -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; } } } diff --git a/src/test/ui/issues/issue-1962.rs b/src/test/ui/issues/issue-1962.rs index 00d2bbd2850..71e87410087 100644 --- a/src/test/ui/issues/issue-1962.rs +++ b/src/test/ui/issues/issue-1962.rs @@ -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; } } } diff --git a/src/test/ui/issues/issue-1962.stderr b/src/test/ui/issues/issue-1962.stderr index 17142912696..4c32a4cf3dd 100644 --- a/src/test/ui/issues/issue-1962.stderr +++ b/src/test/ui/issues/issue-1962.stderr @@ -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` diff --git a/src/test/ui/issues/issue-27042.stderr b/src/test/ui/issues/issue-27042.stderr index 7dee1a6a5f0..59ef28481d0 100644 --- a/src/test/ui/issues/issue-27042.stderr +++ b/src/test/ui/issues/issue-27042.stderr @@ -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 diff --git a/src/test/ui/label/label_misspelled.rs b/src/test/ui/label/label_misspelled.rs index ebfd5642c9f..7a8ff0360f6 100644 --- a/src/test/ui/label/label_misspelled.rs +++ b/src/test/ui/label/label_misspelled.rs @@ -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 + }; +} diff --git a/src/test/ui/label/label_misspelled.stderr b/src/test/ui/label/label_misspelled.stderr index 1368ca4126c..8282d3ada32 100644 --- a/src/test/ui/label/label_misspelled.stderr +++ b/src/test/ui/label/label_misspelled.stderr @@ -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`.