diff --git a/clippy_lints/src/semicolon_if_nothing_returned.rs b/clippy_lints/src/semicolon_if_nothing_returned.rs index 22cd10ced18..628725c52e9 100644 --- a/clippy_lints/src/semicolon_if_nothing_returned.rs +++ b/clippy_lints/src/semicolon_if_nothing_returned.rs @@ -1,7 +1,7 @@ -use crate::utils::{in_macro, span_lint_and_then, sugg}; +use crate::utils::{in_macro, span_lint_and_sugg, sugg, snippet_with_macro_callsite}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Block, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -11,7 +11,6 @@ /// /// **Why is this bad?** The semicolon might be optional but when /// extending the block with new code, it doesn't require a change in previous last line. - /// It's also more idiomatic. /// /// **Known problems:** None. /// @@ -29,7 +28,7 @@ /// } /// ``` pub SEMICOLON_IF_NOTHING_RETURNED, - pedantic, + restriction, "add a semicolon if nothing is returned" } @@ -42,31 +41,25 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if let Some(expr) = block.expr; let t_expr = cx.typeck_results().expr_ty(expr); if t_expr.is_unit(); + if let snippet = snippet_with_macro_callsite(cx, expr.span, "}"); + if !snippet.ends_with('}'); then { - match expr.kind { - ExprKind::Loop(..) | - ExprKind::Match(..) | - ExprKind::Block(..) | - ExprKind::If(..) if !in_macro(expr.span) => return, - _ => (), + // filter out the desugared `for` loop + if let ExprKind::DropTemps(..) = &expr.kind { + return; } let sugg = sugg::Sugg::hir(cx, &expr, ".."); let suggestion = format!("{0};", sugg); - span_lint_and_then( + span_lint_and_sugg( cx, SEMICOLON_IF_NOTHING_RETURNED, expr.span, - "add `;` to terminate block", - | diag | { - diag.span_suggestion( - expr.span, - "add `;`", - suggestion, - Applicability::MaybeIncorrect, - ); - } - ) + "consider adding a `;` to the last statement for consistent formatting", + "add a `;` here", + suggestion, + Applicability::MaybeIncorrect, + ); } } } diff --git a/tests/ui/semicolon_if_nothing_returned.rs b/tests/ui/semicolon_if_nothing_returned.rs index 2c07cc9df40..0abe2cca267 100644 --- a/tests/ui/semicolon_if_nothing_returned.rs +++ b/tests/ui/semicolon_if_nothing_returned.rs @@ -46,3 +46,10 @@ fn foobar(x: i32) { y = x + 1; } } + +fn loop_test(x: i32) { + let y: i32; + for &ext in &["stdout", "stderr", "fixed"] { + println!("{}", ext); + } +} diff --git a/tests/ui/semicolon_if_nothing_returned.stderr b/tests/ui/semicolon_if_nothing_returned.stderr index 6026320f4b4..56211ff7f77 100644 --- a/tests/ui/semicolon_if_nothing_returned.stderr +++ b/tests/ui/semicolon_if_nothing_returned.stderr @@ -1,4 +1,4 @@ -error: add `;` to terminate block +error: consider adding a `;` to the last statement for consistent formatting --> $DIR/semicolon_if_nothing_returned.rs:8:5 | LL | println!("Hello") @@ -7,17 +7,17 @@ LL | println!("Hello") = note: `-D clippy::semicolon-if-nothing-returned` implied by `-D warnings` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: add `;` to terminate block +error: consider adding a `;` to the last statement for consistent formatting --> $DIR/semicolon_if_nothing_returned.rs:12:5 | LL | get_unit() - | ^^^^^^^^^^ help: add `;`: `get_unit();` + | ^^^^^^^^^^ help: add a `;` here: `get_unit();` -error: add `;` to terminate block +error: consider adding a `;` to the last statement for consistent formatting --> $DIR/semicolon_if_nothing_returned.rs:17:5 | LL | y = x + 1 - | ^^^^^^^^^ help: add `;`: `y = x + 1;` + | ^^^^^^^^^ help: add a `;` here: `y = x + 1;` error: aborting due to 3 previous errors