From 547735457ff698dd44ba818a65d1f10853fbeb8e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Jun 2019 01:30:24 +0200 Subject: [PATCH] Make WhileTrue into an EarlyLintPass lint. --- src/librustc_lint/builtin.rs | 44 ++++++++----------- src/librustc_lint/lib.rs | 2 +- src/test/compile-fail/issue-52443.rs | 1 + .../block-must-not-have-result-while.rs | 2 +- .../block-must-not-have-result-while.stderr | 8 ++++ src/test/ui/borrowck/mut-borrow-in-loop.rs | 2 +- .../ui/borrowck/mut-borrow-in-loop.stderr | 8 ++++ src/test/ui/issues/issue-27042.rs | 1 + src/test/ui/issues/issue-27042.stderr | 15 ++++++- src/test/ui/lint/lint-impl-fn.stderr | 24 +++++----- src/test/ui/lint/lint-unnecessary-parens.rs | 1 + .../ui/lint/lint-unnecessary-parens.stderr | 22 +++++++--- src/test/ui/lint/suggestions.stderr | 16 +++---- .../ui/liveness/liveness-move-in-while.rs | 3 ++ .../ui/liveness/liveness-move-in-while.stderr | 20 +++++++++ src/test/ui/loops/loop-break-value.rs | 2 +- src/test/ui/loops/loop-break-value.stderr | 8 ++++ 17 files changed, 120 insertions(+), 59 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d98dfb5478a..c9605445c24 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -64,38 +64,30 @@ declare_lint! { declare_lint_pass!(WhileTrue => [WHILE_TRUE]); -fn as_while_cond(expr: &hir::Expr) -> Option<&hir::Expr> { - if let hir::ExprKind::Loop(blk, ..) = &expr.node { - if let Some(match_expr) = &blk.expr { - if let hir::ExprKind::Match(cond, .., hir::MatchSource::WhileDesugar) - = &match_expr.node - { - if let hir::ExprKind::DropTemps(cond) = &cond.node { - return Some(cond); - } - } - } +/// Traverse through any amount of parenthesis and return the first non-parens expression. +fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { + while let ast::ExprKind::Paren(sub) = &expr.node { + expr = sub; } - - None + expr } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) { - if let Some(ref cond) = as_while_cond(e) { - if let hir::ExprKind::Lit(ref lit) = cond.node { +impl EarlyLintPass for WhileTrue { + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + if let ast::ExprKind::While(cond, ..) = &e.node { + if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).node { if let ast::LitKind::Bool(true) = lit.node { if lit.span.ctxt() == SyntaxContext::empty() { let msg = "denote infinite loops with `loop { ... }`"; - let condition_span = cx.tcx.sess.source_map().def_span(e.span); - let mut err = cx.struct_span_lint(WHILE_TRUE, condition_span, msg); - err.span_suggestion_short( - condition_span, - "use `loop`", - "loop".to_owned(), - Applicability::MachineApplicable - ); - err.emit(); + let condition_span = cx.sess.source_map().def_span(e.span); + cx.struct_span_lint(WHILE_TRUE, condition_span, msg) + .span_suggestion_short( + condition_span, + "use `loop`", + "loop".to_owned(), + Applicability::MachineApplicable + ) + .emit(); } } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index fb02782e6d3..2519981fa21 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -96,6 +96,7 @@ macro_rules! early_lint_passes { EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), NonCamelCaseTypes: NonCamelCaseTypes, DeprecatedAttr: DeprecatedAttr::new(), + WhileTrue: WhileTrue, ]); ) } @@ -140,7 +141,6 @@ macro_rules! late_lint_mod_passes { ($macro:path, $args:tt) => ( $macro!($args, [ HardwiredLints: HardwiredLints, - WhileTrue: WhileTrue, ImproperCTypes: ImproperCTypes, VariantSizeDifferences: VariantSizeDifferences, BoxPointers: BoxPointers, diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs index 0d6906086e9..a993d811d32 100644 --- a/src/test/compile-fail/issue-52443.rs +++ b/src/test/compile-fail/issue-52443.rs @@ -2,6 +2,7 @@ fn main() { [(); & { loop { continue } } ]; //~ ERROR mismatched types [(); loop { break }]; //~ ERROR mismatched types [(); {while true {break}; 0}]; //~ ERROR constant contains unimplemented expression type + //~^ WARN denote infinite loops with [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions //~^ ERROR constant contains unimplemented expression type //~| ERROR constant contains unimplemented expression type diff --git a/src/test/ui/block-result/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs index 96597631396..108b9bc9e9b 100644 --- a/src/test/ui/block-result/block-must-not-have-result-while.rs +++ b/src/test/ui/block-result/block-must-not-have-result-while.rs @@ -1,5 +1,5 @@ fn main() { - while true { + while true { //~ WARN denote infinite loops with true //~ ERROR mismatched types //~| expected type `()` //~| found type `bool` diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr index 302d2972f7d..c41afcc9121 100644 --- a/src/test/ui/block-result/block-must-not-have-result-while.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/block-must-not-have-result-while.rs:2:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + error[E0308]: mismatched types --> $DIR/block-must-not-have-result-while.rs:3:9 | diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.rs b/src/test/ui/borrowck/mut-borrow-in-loop.rs index 09f3e4f9b76..22667906e12 100644 --- a/src/test/ui/borrowck/mut-borrow-in-loop.rs +++ b/src/test/ui/borrowck/mut-borrow-in-loop.rs @@ -12,7 +12,7 @@ impl<'a, T : 'a> FuncWrapper<'a, T> { } fn in_while(self, arg : &'a mut T) { - while true { + while true { //~ WARN denote infinite loops with (self.func)(arg) //~ ERROR cannot borrow } } diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.stderr index eda2f518f92..59cf4d533de 100644 --- a/src/test/ui/borrowck/mut-borrow-in-loop.stderr +++ b/src/test/ui/borrowck/mut-borrow-in-loop.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/mut-borrow-in-loop.rs:15:9 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + error[E0499]: cannot borrow `*arg` as mutable more than once at a time --> $DIR/mut-borrow-in-loop.rs:10:25 | diff --git a/src/test/ui/issues/issue-27042.rs b/src/test/ui/issues/issue-27042.rs index 8c7758597f0..517c1f2e6c7 100644 --- a/src/test/ui/issues/issue-27042.rs +++ b/src/test/ui/issues/issue-27042.rs @@ -6,6 +6,7 @@ fn main() { loop { break }; //~ ERROR mismatched types let _: i32 = 'b: //~ ERROR mismatched types + //~^ WARN denote infinite loops with while true { break }; // but here we cite the whole loop let _: i32 = 'c: //~ ERROR mismatched types diff --git a/src/test/ui/issues/issue-27042.stderr b/src/test/ui/issues/issue-27042.stderr index cce7d24a5f6..c67b8ad7381 100644 --- a/src/test/ui/issues/issue-27042.stderr +++ b/src/test/ui/issues/issue-27042.stderr @@ -1,3 +1,13 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/issue-27042.rs:8:9 + | +LL | / 'b: +LL | | +LL | | while true { break }; // but here we cite the whole loop + | |____________________________^ help: use `loop` + | + = note: #[warn(while_true)] on by default + error[E0308]: mismatched types --> $DIR/issue-27042.rs:6:16 | @@ -11,6 +21,7 @@ error[E0308]: mismatched types --> $DIR/issue-27042.rs:8:9 | LL | / 'b: +LL | | LL | | while true { break }; // but here we cite the whole loop | |____________________________^ expected i32, found () | @@ -18,7 +29,7 @@ LL | | while true { break }; // but here we cite the whole loop found type `()` error[E0308]: mismatched types - --> $DIR/issue-27042.rs:11:9 + --> $DIR/issue-27042.rs:12:9 | LL | / 'c: LL | | for _ in None { break }; // but here we cite the whole loop @@ -28,7 +39,7 @@ LL | | for _ in None { break }; // but here we cite the whole loop found type `()` error[E0308]: mismatched types - --> $DIR/issue-27042.rs:14:9 + --> $DIR/issue-27042.rs:15:9 | LL | / 'd: LL | | while let Some(_) = None { break }; diff --git a/src/test/ui/lint/lint-impl-fn.stderr b/src/test/ui/lint/lint-impl-fn.stderr index 56f85111d42..2c9a264287c 100644 --- a/src/test/ui/lint/lint-impl-fn.stderr +++ b/src/test/ui/lint/lint-impl-fn.stderr @@ -10,18 +10,6 @@ note: lint level defined here LL | #[deny(while_true)] | ^^^^^^^^^^ -error: denote infinite loops with `loop { ... }` - --> $DIR/lint-impl-fn.rs:27:5 - | -LL | while true {} - | ^^^^^^^^^^ help: use `loop` - | -note: lint level defined here - --> $DIR/lint-impl-fn.rs:25:8 - | -LL | #[deny(while_true)] - | ^^^^^^^^^^ - error: denote infinite loops with `loop { ... }` --> $DIR/lint-impl-fn.rs:18:25 | @@ -34,5 +22,17 @@ note: lint level defined here LL | #[deny(while_true)] | ^^^^^^^^^^ +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:27:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: lint level defined here + --> $DIR/lint-impl-fn.rs:25:8 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs index c36101043a7..811bc87eb0e 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.rs +++ b/src/test/ui/lint/lint-unnecessary-parens.rs @@ -19,6 +19,7 @@ fn main() { if (true) {} //~ ERROR unnecessary parentheses around `if` condition while (true) {} //~ ERROR unnecessary parentheses around `while` condition + //~^ WARN denote infinite loops with match (true) { //~ ERROR unnecessary parentheses around `match` head expression _ => {} } diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr index dfbefd7b03e..05ecbfdf4fa 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.stderr +++ b/src/test/ui/lint/lint-unnecessary-parens.stderr @@ -34,44 +34,52 @@ error: unnecessary parentheses around `while` condition LL | while (true) {} | ^^^^^^ help: remove these parentheses +warning: denote infinite loops with `loop { ... }` + --> $DIR/lint-unnecessary-parens.rs:21:5 + | +LL | while (true) {} + | ^^^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + error: unnecessary parentheses around `match` head expression - --> $DIR/lint-unnecessary-parens.rs:22:11 + --> $DIR/lint-unnecessary-parens.rs:23:11 | LL | match (true) { | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `let` head expression - --> $DIR/lint-unnecessary-parens.rs:25:16 + --> $DIR/lint-unnecessary-parens.rs:26:16 | LL | if let 1 = (1) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around `let` head expression - --> $DIR/lint-unnecessary-parens.rs:26:19 + --> $DIR/lint-unnecessary-parens.rs:27:19 | LL | while let 1 = (2) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around method argument - --> $DIR/lint-unnecessary-parens.rs:40:24 + --> $DIR/lint-unnecessary-parens.rs:41:24 | LL | X { y: false }.foo((true)); | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:42:18 + --> $DIR/lint-unnecessary-parens.rs:43:18 | LL | let mut _a = (0); | ^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:43:10 + --> $DIR/lint-unnecessary-parens.rs:44:10 | LL | _a = (0); | ^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:44:11 + --> $DIR/lint-unnecessary-parens.rs:45:11 | LL | _a += (1); | ^^^ help: remove these parentheses diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 5aaa9947f99..de7c1fb8986 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/suggestions.rs:46:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + warning: unnecessary parentheses around assigned value --> $DIR/suggestions.rs:49:31 | @@ -65,14 +73,6 @@ LL | pub fn defiant(_t: T) {} | = note: #[warn(no_mangle_generic_items)] on by default -warning: denote infinite loops with `loop { ... }` - --> $DIR/suggestions.rs:46:5 - | -LL | while true { - | ^^^^^^^^^^ help: use `loop` - | - = note: #[warn(while_true)] on by default - warning: the `warp_factor:` in this pattern is redundant --> $DIR/suggestions.rs:61:23 | diff --git a/src/test/ui/liveness/liveness-move-in-while.rs b/src/test/ui/liveness/liveness-move-in-while.rs index 420d1311f8b..9f3ebf1362b 100644 --- a/src/test/ui/liveness/liveness-move-in-while.rs +++ b/src/test/ui/liveness/liveness-move-in-while.rs @@ -6,5 +6,8 @@ fn main() { loop { println!("{}", y); //~ ERROR borrow of moved value: `y` while true { while true { while true { x = y; x.clone(); } } } + //~^ WARN denote infinite loops with + //~| WARN denote infinite loops with + //~| WARN denote infinite loops with } } diff --git a/src/test/ui/liveness/liveness-move-in-while.stderr b/src/test/ui/liveness/liveness-move-in-while.stderr index e1eed1b59f4..bbf5e50f1e0 100644 --- a/src/test/ui/liveness/liveness-move-in-while.stderr +++ b/src/test/ui/liveness/liveness-move-in-while.stderr @@ -1,3 +1,23 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/liveness-move-in-while.rs:8:9 + | +LL | while true { while true { while true { x = y; x.clone(); } } } + | ^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + +warning: denote infinite loops with `loop { ... }` + --> $DIR/liveness-move-in-while.rs:8:22 + | +LL | while true { while true { while true { x = y; x.clone(); } } } + | ^^^^^^^^^^ help: use `loop` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/liveness-move-in-while.rs:8:35 + | +LL | while true { while true { while true { x = y; x.clone(); } } } + | ^^^^^^^^^^ help: use `loop` + error[E0382]: borrow of moved value: `y` --> $DIR/liveness-move-in-while.rs:7:24 | diff --git a/src/test/ui/loops/loop-break-value.rs b/src/test/ui/loops/loop-break-value.rs index b80c847deb9..7c2f63ec51a 100644 --- a/src/test/ui/loops/loop-break-value.rs +++ b/src/test/ui/loops/loop-break-value.rs @@ -23,7 +23,7 @@ fn main() { }; }; - 'while_loop: while true { + 'while_loop: while true { //~ WARN denote infinite loops with break; break (); //~ ERROR `break` with value from a `while` loop loop { diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 13fe5085540..f458c88ea48 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/loop-break-value.rs:26:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + | + = note: #[warn(while_true)] on by default + error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:28:9 |