diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index c0605b2f4121c..90d814d05cf01 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -14,19 +14,19 @@ use crate::thread::Result; #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")] #[rustc_macro_transparency = "semitransparent"] pub macro panic_2015 { - () => ({ + () => ( $crate::rt::begin_panic("explicit panic") - }), - ($msg:expr $(,)?) => ({ + ), + ($msg:expr $(,)?) => ( $crate::rt::begin_panic($msg) - }), + ), // Special-case the single-argument case for const_panic. - ("{}", $arg:expr $(,)?) => ({ + ("{}", $arg:expr $(,)?) => ( $crate::rt::panic_display(&$arg) - }), - ($fmt:expr, $($arg:tt)+) => ({ + ), + ($fmt:expr, $($arg:tt)+) => ( $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) - }), + ), } #[doc(hidden)] diff --git a/src/test/ui/block-result/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs index 577987a4596cb..f42482bb9ff90 100644 --- a/src/test/ui/block-result/issue-5500.rs +++ b/src/test/ui/block-result/issue-5500.rs @@ -2,6 +2,6 @@ fn main() { &panic!() //~^ ERROR mismatched types //~| expected unit type `()` - //~| found reference `&_` - //~| expected `()`, found reference + //~| found reference `&!` + //~| expected `()`, found `&!` } diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index 7081b5106ff96..3adb5cba7b836 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -4,15 +4,10 @@ error[E0308]: mismatched types LL | fn main() { | - expected `()` because of default return type LL | &panic!() - | ^^^^^^^^^ expected `()`, found reference + | ^^^^^^^^^ expected `()`, found `&!` | = note: expected unit type `()` - found reference `&_` -help: consider removing the borrow - | -LL - &panic!() -LL + panic!() - | + found reference `&!` error: aborting due to previous error diff --git a/src/test/ui/diverging-tuple-parts-39485.stderr b/src/test/ui/diverging-tuple-parts-39485.stderr index 32967b376ca9c..4a82124c542db 100644 --- a/src/test/ui/diverging-tuple-parts-39485.stderr +++ b/src/test/ui/diverging-tuple-parts-39485.stderr @@ -1,20 +1,13 @@ error[E0308]: mismatched types --> $DIR/diverging-tuple-parts-39485.rs:8:5 | +LL | fn g() { + | - help: try adding a return type: `-> &!` LL | &panic!() - | ^^^^^^^^^ expected `()`, found reference + | ^^^^^^^^^ expected `()`, found `&!` | = note: expected unit type `()` - found reference `&_` -help: try adding a return type - | -LL | fn g() -> &_ { - | +++++ -help: consider removing the borrow - | -LL - &panic!() -LL + panic!() - | + found reference `&!` error[E0308]: mismatched types --> $DIR/diverging-tuple-parts-39485.rs:12:5 diff --git a/src/test/ui/issues/issue-5500-1.rs b/src/test/ui/issues/issue-5500-1.rs index 98d6e1a14cb32..6cafe19bc2669 100644 --- a/src/test/ui/issues/issue-5500-1.rs +++ b/src/test/ui/issues/issue-5500-1.rs @@ -11,5 +11,5 @@ struct TrieMapIterator<'a> { fn main() { let a = 5; let _iter = TrieMapIterator{node: &a}; - _iter.node = &panic!() + _iter.node = &{panic!()} } diff --git a/src/tools/clippy/clippy_lints/src/if_then_panic.rs b/src/tools/clippy/clippy_lints/src/if_then_panic.rs index 10bca59e6d06a..aa3547f5a07df 100644 --- a/src/tools/clippy/clippy_lints/src/if_then_panic.rs +++ b/src/tools/clippy/clippy_lints/src/if_then_panic.rs @@ -61,9 +61,7 @@ impl LateLintPass<'_> for IfThenPanic { } } else { if_chain! { - if let ExprKind::Block(block, _) = semi.kind; - if let Some(init) = block.expr; - if let ExprKind::Call(_, [format_args]) = init.kind; + if let ExprKind::Call(_, [format_args]) = semi.kind; then { format_args.span diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index 56d4163a6b343..cee9dcf4747b5 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -968,8 +968,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm } if_chain! { if matching_wild; - if let ExprKind::Block(block, _) = arm.body.kind; - if is_panic_block(block); + if is_panic_call(arm.body); then { // `Err(_)` or `Err(_e)` arm with `panic!` found span_lint_and_note(cx, @@ -1172,14 +1171,19 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) } // If the block contains only a `panic!` macro (as expression or statement) -fn is_panic_block(block: &Block<'_>) -> bool { - match (&block.expr, block.stmts.len(), block.stmts.first()) { - (&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(), - (&None, 1, Some(stmt)) => { - is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none() - }, - _ => false, - } +fn is_panic_call(expr: &Expr<'_>) -> bool { + // Unwrap any wrapping blocks + let span = if let ExprKind::Block(block, _) = expr.kind { + match (&block.expr, block.stmts.len(), block.stmts.first()) { + (&Some(exp), 0, _) => exp.span, + (&None, 1, Some(stmt)) => stmt.span, + _ => return false, + } + } else { + expr.span + }; + + is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none() } fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>) diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 74cf323720cbb..09d6b8a333789 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -615,9 +615,7 @@ impl PanicExpn<'tcx> { /// Parses an expanded `panic!` invocation pub fn parse(expr: &'tcx Expr<'tcx>) -> Option { if_chain! { - if let ExprKind::Block(block, _) = expr.kind; - if let Some(init) = block.expr; - if let ExprKind::Call(_, [format_args]) = init.kind; + if let ExprKind::Call(_, [format_args]) = expr.kind; let expn_data = expr.span.ctxt().outer_expn_data(); if let Some(format_args) = FormatArgsExpn::parse(format_args); then { diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr index 170e7d92de4ac..a588c8ff4e7b2 100644 --- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr +++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr @@ -30,11 +30,19 @@ error: sub-expression diverges LL | 3 => true || diverge(), | ^^^^^^^^^ +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:37:30 + | +LL | _ => true || panic!("boo"), + | ^^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:39:26 | LL | _ => true || break, | ^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/if_then_panic_core.fixed b/src/tools/clippy/tests/ui/if_then_panic_core.fixed new file mode 100644 index 0000000000000..2322fba398039 --- /dev/null +++ b/src/tools/clippy/tests/ui/if_then_panic_core.fixed @@ -0,0 +1,42 @@ +// run-rustfix +#![crate_type = "lib"] +#![no_std] +#![warn(clippy::if_then_panic)] + +pub fn main() { + let a = &[1, 2, 3]; + let c = Some(2); + if !a.is_empty() + && a.len() == 3 + && c != None + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + { + panic!("qaqaq{:?}", a); + } + assert!(a.is_empty(), "qaqaq{:?}", a); + assert!(a.is_empty(), "qwqwq"); + if a.len() == 3 { + format_args!("qwq"); + format_args!("qwq"); + format_args!("qwq"); + } + if let Some(b) = c { + panic!("orz {}", b); + } + if a.len() == 3 { + panic!("qaqaq"); + } else { + format_args!("qwq"); + } + let b = &[1, 2, 3]; + assert!(!b.is_empty(), "panic1"); + assert!(!(b.is_empty() && a.is_empty()), "panic2"); + assert!(!(a.is_empty() && !b.is_empty()), "panic3"); + assert!(!(b.is_empty() || a.is_empty()), "panic4"); + assert!(!(a.is_empty() || !b.is_empty()), "panic5"); +} diff --git a/src/tools/clippy/tests/ui/if_then_panic_core.rs b/src/tools/clippy/tests/ui/if_then_panic_core.rs new file mode 100644 index 0000000000000..fb7be9a25c19d --- /dev/null +++ b/src/tools/clippy/tests/ui/if_then_panic_core.rs @@ -0,0 +1,56 @@ +// run-rustfix +#![crate_type = "lib"] +#![no_std] +#![warn(clippy::if_then_panic)] + +pub fn main() { + let a = &[1, 2, 3]; + let c = Some(2); + if !a.is_empty() + && a.len() == 3 + && c != None + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + { + panic!("qaqaq{:?}", a); + } + if !a.is_empty() { + panic!("qaqaq{:?}", a); + } + if !a.is_empty() { + panic!("qwqwq"); + } + if a.len() == 3 { + format_args!("qwq"); + format_args!("qwq"); + format_args!("qwq"); + } + if let Some(b) = c { + panic!("orz {}", b); + } + if a.len() == 3 { + panic!("qaqaq"); + } else { + format_args!("qwq"); + } + let b = &[1, 2, 3]; + if b.is_empty() { + panic!("panic1"); + } + if b.is_empty() && a.is_empty() { + panic!("panic2"); + } + if a.is_empty() && !b.is_empty() { + panic!("panic3"); + } + if b.is_empty() || a.is_empty() { + panic!("panic4"); + } + if a.is_empty() || !b.is_empty() { + panic!("panic5"); + } +} diff --git a/src/tools/clippy/tests/ui/if_then_panic_core.stderr b/src/tools/clippy/tests/ui/if_then_panic_core.stderr new file mode 100644 index 0000000000000..688ed0b98a4a9 --- /dev/null +++ b/src/tools/clippy/tests/ui/if_then_panic_core.stderr @@ -0,0 +1,60 @@ +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:21:5 + | +LL | / if !a.is_empty() { +LL | | panic!("qaqaq{:?}", a); +LL | | } + | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);` + | + = note: `-D clippy::if-then-panic` implied by `-D warnings` + +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:24:5 + | +LL | / if !a.is_empty() { +LL | | panic!("qwqwq"); +LL | | } + | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");` + +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:41:5 + | +LL | / if b.is_empty() { +LL | | panic!("panic1"); +LL | | } + | |_____^ help: try: `assert!(!b.is_empty(), "panic1");` + +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:44:5 + | +LL | / if b.is_empty() && a.is_empty() { +LL | | panic!("panic2"); +LL | | } + | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");` + +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:47:5 + | +LL | / if a.is_empty() && !b.is_empty() { +LL | | panic!("panic3"); +LL | | } + | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");` + +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:50:5 + | +LL | / if b.is_empty() || a.is_empty() { +LL | | panic!("panic4"); +LL | | } + | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");` + +error: only a `panic!` in `if`-then statement + --> $DIR/if_then_panic_core.rs:53:5 + | +LL | / if a.is_empty() || !b.is_empty() { +LL | | panic!("panic5"); +LL | | } + | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");` + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/issue-7447.rs b/src/tools/clippy/tests/ui/issue-7447.rs index fdb77f322579f..fd9f49736a0bc 100644 --- a/src/tools/clippy/tests/ui/issue-7447.rs +++ b/src/tools/clippy/tests/ui/issue-7447.rs @@ -19,6 +19,7 @@ pub struct ByteView<'a> { backing: Arc>, } +#[allow(clippy::diverging_sub_expression)] fn main() { byte_view(panic!()); group_entries(panic!());