Auto merge of #12536 - samueltardieu:issue-12505, r=Manishearth

`manual_assert`: do not add extra semicolon

Fixes #12505

changelog: [`manual_assert`]: do not add extra semicolon to suggestion
This commit is contained in:
bors 2024-03-25 20:07:54 +00:00
commit b1b7352880
8 changed files with 61 additions and 13 deletions

View file

@ -1,7 +1,7 @@
use crate::rustc_lint::LintContext; use crate::rustc_lint::LintContext;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::root_macro_call; use clippy_utils::macros::root_macro_call;
use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg}; use clippy_utils::{is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -63,7 +63,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
_ => (cond, "!"), _ => (cond, "!"),
}; };
let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par(); let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});"); let semicolon = if is_parent_stmt(cx, expr.hir_id) { ";" } else { "" };
let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip}){semicolon}");
// we show to the user the suggestion without the comments, but when applying the fix, include the // we show to the user the suggestion without the comments, but when applying the fix, include the
// comments in the block // comments in the block
span_lint_and_then( span_lint_and_then(

View file

@ -6,11 +6,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use clippy_utils::{ use clippy_utils::{
higher, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq, higher, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt, span_extract_comment,
SpanlessEq,
}; };
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
@ -135,13 +136,6 @@ fn condition_needs_parentheses(e: &Expr<'_>) -> bool {
false false
} }
fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
matches!(
cx.tcx.parent_hir_node(id),
Node::Stmt(..) | Node::Block(Block { stmts: &[], .. })
)
}
impl<'tcx> LateLintPass<'tcx> for NeedlessBool { impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
use self::Expression::{Bool, RetBool}; use self::Expression::{Bool, RetBool};

View file

@ -3335,3 +3335,12 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
repeat(String::from("super")).take(go_up_by).chain(path).join("::") repeat(String::from("super")).take(go_up_by).chain(path).join("::")
} }
} }
/// Returns true if the specified `HirId` is the top-level expression of a statement or the only
/// expression in a block.
pub fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
matches!(
cx.tcx.parent_hir_node(id),
Node::Stmt(..) | Node::Block(Block { stmts: &[], .. })
)
}

View file

@ -66,3 +66,11 @@ fn issue7730(a: u8) {
// comment after `panic!` // comment after `panic!`
assert!(!(a > 2), "panic with comment"); assert!(!(a > 2), "panic with comment");
} }
fn issue12505() {
struct Foo<T, const N: usize>(T);
impl<T, const N: usize> Foo<T, N> {
const BAR: () = assert!(!(N == 0), );
}
}

View file

@ -82,5 +82,14 @@ help: try instead
LL | assert!(!(a > 2), "panic with comment"); LL | assert!(!(a > 2), "panic with comment");
| |
error: aborting due to 9 previous errors error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:91:25
|
LL | const BAR: () = if N == 0 {
| _________________________^
LL | | panic!()
LL | | };
| |_________^ help: try instead: `assert!(!(N == 0), )`
error: aborting due to 10 previous errors

View file

@ -66,3 +66,11 @@ fn issue7730(a: u8) {
// comment after `panic!` // comment after `panic!`
assert!(!(a > 2), "panic with comment"); assert!(!(a > 2), "panic with comment");
} }
fn issue12505() {
struct Foo<T, const N: usize>(T);
impl<T, const N: usize> Foo<T, N> {
const BAR: () = assert!(!(N == 0), );
}
}

View file

@ -82,5 +82,14 @@ help: try instead
LL | assert!(!(a > 2), "panic with comment"); LL | assert!(!(a > 2), "panic with comment");
| |
error: aborting due to 9 previous errors error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:91:25
|
LL | const BAR: () = if N == 0 {
| _________________________^
LL | | panic!()
LL | | };
| |_________^ help: try instead: `assert!(!(N == 0), )`
error: aborting due to 10 previous errors

View file

@ -83,3 +83,13 @@ fn issue7730(a: u8) {
panic!("panic with comment") // comment after `panic!` panic!("panic with comment") // comment after `panic!`
} }
} }
fn issue12505() {
struct Foo<T, const N: usize>(T);
impl<T, const N: usize> Foo<T, N> {
const BAR: () = if N == 0 {
panic!()
};
}
}