1
Fork 0

Rollup merge of #81645 - m-ou-se:panic-lint, r=estebank,flip1995

Add lint for `panic!(123)` which is not accepted in Rust 2021.

This extends the `panic_fmt` lint to warn for all cases where the first argument cannot be interpreted as a format string, as will happen in Rust 2021.

It suggests to add `"{}",` to format the message as a string. In the case of `std::panic!()`, it also suggests the recently stabilized
`std::panic::panic_any()` function as an alternative.

It renames the lint to `non_fmt_panic` to match the lint naming guidelines.

![image](https://user-images.githubusercontent.com/783247/106520928-675ea680-64d5-11eb-81f7-d8fa48b93a0b.png)

This is part of #80162.

r? ```@estebank```
This commit is contained in:
Mara Bos 2021-02-04 21:10:36 +01:00 committed by GitHub
commit 87b269ab66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 396 additions and 258 deletions

View file

@ -28,7 +28,7 @@ pub trait ExpectOne<A: Array> {
impl<A: Array> ExpectOne<A> for SmallVec<A> { impl<A: Array> ExpectOne<A> for SmallVec<A> {
fn expect_one(self, err: &'static str) -> A::Item { fn expect_one(self, err: &'static str) -> A::Item {
assert!(self.len() == 1, err); assert!(self.len() == 1, "{}", err);
self.into_iter().next().unwrap() self.into_iter().next().unwrap()
} }
} }

View file

@ -901,7 +901,7 @@ impl HandlerInner {
fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ! { fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ! {
self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp); self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp);
panic!(ExplicitBug); panic::panic_any(ExplicitBug);
} }
fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) { fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
@ -955,7 +955,7 @@ impl HandlerInner {
fn bug(&mut self, msg: &str) -> ! { fn bug(&mut self, msg: &str) -> ! {
self.emit_diagnostic(&Diagnostic::new(Bug, msg)); self.emit_diagnostic(&Diagnostic::new(Bug, msg));
panic!(ExplicitBug); panic::panic_any(ExplicitBug);
} }
fn delay_as_bug(&mut self, diagnostic: Diagnostic) { fn delay_as_bug(&mut self, diagnostic: Diagnostic) {

View file

@ -55,8 +55,8 @@ mod late;
mod levels; mod levels;
mod methods; mod methods;
mod non_ascii_idents; mod non_ascii_idents;
mod non_fmt_panic;
mod nonstandard_style; mod nonstandard_style;
mod panic_fmt;
mod passes; mod passes;
mod redundant_semicolon; mod redundant_semicolon;
mod traits; mod traits;
@ -81,8 +81,8 @@ use builtin::*;
use internal::*; use internal::*;
use methods::*; use methods::*;
use non_ascii_idents::*; use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
use nonstandard_style::*; use nonstandard_style::*;
use panic_fmt::PanicFmt;
use redundant_semicolon::*; use redundant_semicolon::*;
use traits::*; use traits::*;
use types::*; use types::*;
@ -169,7 +169,7 @@ macro_rules! late_lint_passes {
ClashingExternDeclarations: ClashingExternDeclarations::new(), ClashingExternDeclarations: ClashingExternDeclarations::new(),
DropTraitConstraints: DropTraitConstraints, DropTraitConstraints: DropTraitConstraints,
TemporaryCStringAsPtr: TemporaryCStringAsPtr, TemporaryCStringAsPtr: TemporaryCStringAsPtr,
PanicFmt: PanicFmt, NonPanicFmt: NonPanicFmt,
] ]
); );
}; };

View file

@ -0,0 +1,197 @@
use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::{pluralize, Applicability};
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_span::{sym, symbol::kw, InnerSpan, Span, Symbol};
declare_lint! {
/// The `non_fmt_panic` lint detects `panic!(..)` invocations where the first
/// argument is not a formatting string.
///
/// ### Example
///
/// ```rust,no_run
/// panic!("{}");
/// panic!(123);
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// In Rust 2018 and earlier, `panic!(x)` directly uses `x` as the message.
/// That means that `panic!("{}")` panics with the message `"{}"` instead
/// of using it as a formatting string, and `panic!(123)` will panic with
/// an `i32` as message.
///
/// Rust 2021 always interprets the first argument as format string.
NON_FMT_PANIC,
Warn,
"detect single-argument panic!() invocations in which the argument is not a format string",
report_in_external_macro
}
declare_lint_pass!(NonPanicFmt => [NON_FMT_PANIC]);
impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
|| Some(def_id) == cx.tcx.lang_items().panic_fn()
|| Some(def_id) == cx.tcx.lang_items().panic_str()
{
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
if cx.tcx.is_diagnostic_item(sym::std_panic_2015_macro, id)
|| cx.tcx.is_diagnostic_item(sym::core_panic_2015_macro, id)
{
check_panic(cx, f, arg);
}
}
}
}
}
}
}
fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Lit(lit) = &arg.kind {
if let ast::LitKind::Str(sym, _) = lit.node {
// The argument is a string literal.
check_panic_str(cx, f, arg, &sym.as_str());
return;
}
}
// The argument is *not* a string literal.
let (span, panic) = panic_call(cx, f);
cx.struct_span_lint(NON_FMT_PANIC, arg.span, |lint| {
let mut l = lint.build("panic message is not a string literal");
l.note("this is no longer accepted in Rust 2021");
if span.contains(arg.span) {
l.span_suggestion_verbose(
arg.span.shrink_to_lo(),
"add a \"{}\" format string to Display the message",
"\"{}\", ".into(),
Applicability::MaybeIncorrect,
);
if panic == sym::std_panic_macro {
l.span_suggestion_verbose(
span.until(arg.span),
"or use std::panic::panic_any instead",
"std::panic::panic_any(".into(),
Applicability::MachineApplicable,
);
}
}
l.emit();
});
}
fn check_panic_str<'tcx>(
cx: &LateContext<'tcx>,
f: &'tcx hir::Expr<'tcx>,
arg: &'tcx hir::Expr<'tcx>,
fmt: &str,
) {
if !fmt.contains(&['{', '}'][..]) {
// No brace, no problem.
return;
}
let fmt_span = arg.span.source_callsite();
let (snippet, style) = match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
Ok(snippet) => {
// Count the number of `#`s between the `r` and `"`.
let style = snippet.strip_prefix('r').and_then(|s| s.find('"'));
(Some(snippet), style)
}
Err(_) => (None, None),
};
let mut fmt_parser =
Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
let n_arguments = (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
let (span, _) = panic_call(cx, f);
if n_arguments > 0 && fmt_parser.errors.is_empty() {
let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
[] => vec![fmt_span],
v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
};
cx.struct_span_lint(NON_FMT_PANIC, arg_spans, |lint| {
let mut l = lint.build(match n_arguments {
1 => "panic message contains an unused formatting placeholder",
_ => "panic message contains unused formatting placeholders",
});
l.note("this message is not used as a format string when given without arguments, but will be in Rust 2021");
if span.contains(arg.span) {
l.span_suggestion(
arg.span.shrink_to_hi(),
&format!("add the missing argument{}", pluralize!(n_arguments)),
", ...".into(),
Applicability::HasPlaceholders,
);
l.span_suggestion(
arg.span.shrink_to_lo(),
"or add a \"{}\" format string to use the message literally",
"\"{}\", ".into(),
Applicability::MachineApplicable,
);
}
l.emit();
});
} else {
let brace_spans: Option<Vec<_>> =
snippet.filter(|s| s.starts_with('"') || s.starts_with("r#")).map(|s| {
s.char_indices()
.filter(|&(_, c)| c == '{' || c == '}')
.map(|(i, _)| fmt_span.from_inner(InnerSpan { start: i, end: i + 1 }))
.collect()
});
let msg = match &brace_spans {
Some(v) if v.len() == 1 => "panic message contains a brace",
_ => "panic message contains braces",
};
cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or(vec![span]), |lint| {
let mut l = lint.build(msg);
l.note("this message is not used as a format string, but will be in Rust 2021");
if span.contains(arg.span) {
l.span_suggestion(
arg.span.shrink_to_lo(),
"add a \"{}\" format string to use the message literally",
"\"{}\", ".into(),
Applicability::MachineApplicable,
);
}
l.emit();
});
}
}
fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol) {
let mut expn = f.span.ctxt().outer_expn_data();
let mut panic_macro = kw::Empty;
// Unwrap more levels of macro expansion, as panic_2015!()
// was likely expanded from panic!() and possibly from
// [debug_]assert!().
for &i in
&[sym::std_panic_macro, sym::core_panic_macro, sym::assert_macro, sym::debug_assert_macro]
{
let parent = expn.call_site.ctxt().outer_expn_data();
if parent.macro_def_id.map_or(false, |id| cx.tcx.is_diagnostic_item(i, id)) {
expn = parent;
panic_macro = i;
}
}
(expn.call_site, panic_macro)
}

View file

@ -1,155 +0,0 @@
use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::{pluralize, Applicability};
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_span::{sym, InnerSpan};
declare_lint! {
/// The `panic_fmt` lint detects `panic!("..")` with `{` or `}` in the string literal.
///
/// ### Example
///
/// ```rust,no_run
/// panic!("{}");
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// In Rust 2018 and earlier, `panic!("{}")` panics with the message `"{}"`,
/// as a `panic!()` invocation with a single argument does not use `format_args!()`.
/// Rust 2021 interprets this string as format string, which breaks this.
PANIC_FMT,
Warn,
"detect braces in single-argument panic!() invocations",
report_in_external_macro
}
declare_lint_pass!(PanicFmt => [PANIC_FMT]);
impl<'tcx> LateLintPass<'tcx> for PanicFmt {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
|| Some(def_id) == cx.tcx.lang_items().panic_fn()
{
check_panic(cx, f, arg);
}
}
}
}
}
fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Lit(lit) = &arg.kind {
if let ast::LitKind::Str(sym, _) = lit.node {
let mut expn = f.span.ctxt().outer_expn_data();
if let Some(id) = expn.macro_def_id {
if cx.tcx.is_diagnostic_item(sym::std_panic_2015_macro, id)
|| cx.tcx.is_diagnostic_item(sym::core_panic_2015_macro, id)
{
let fmt = sym.as_str();
if !fmt.contains(&['{', '}'][..]) {
return;
}
let fmt_span = arg.span.source_callsite();
let (snippet, style) =
match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
Ok(snippet) => {
// Count the number of `#`s between the `r` and `"`.
let style = snippet.strip_prefix('r').and_then(|s| s.find('"'));
(Some(snippet), style)
}
Err(_) => (None, None),
};
let mut fmt_parser =
Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
let n_arguments =
(&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
// Unwrap more levels of macro expansion, as panic_2015!()
// was likely expanded from panic!() and possibly from
// [debug_]assert!().
for &assert in &[
sym::std_panic_macro,
sym::core_panic_macro,
sym::assert_macro,
sym::debug_assert_macro,
] {
let parent = expn.call_site.ctxt().outer_expn_data();
if parent
.macro_def_id
.map_or(false, |id| cx.tcx.is_diagnostic_item(assert, id))
{
expn = parent;
}
}
if n_arguments > 0 && fmt_parser.errors.is_empty() {
let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
[] => vec![fmt_span],
v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
};
cx.struct_span_lint(PANIC_FMT, arg_spans, |lint| {
let mut l = lint.build(match n_arguments {
1 => "panic message contains an unused formatting placeholder",
_ => "panic message contains unused formatting placeholders",
});
l.note("this message is not used as a format string when given without arguments, but will be in a future Rust edition");
if expn.call_site.contains(arg.span) {
l.span_suggestion(
arg.span.shrink_to_hi(),
&format!("add the missing argument{}", pluralize!(n_arguments)),
", ...".into(),
Applicability::HasPlaceholders,
);
l.span_suggestion(
arg.span.shrink_to_lo(),
"or add a \"{}\" format string to use the message literally",
"\"{}\", ".into(),
Applicability::MachineApplicable,
);
}
l.emit();
});
} else {
let brace_spans: Option<Vec<_>> = snippet
.filter(|s| s.starts_with('"') || s.starts_with("r#"))
.map(|s| {
s.char_indices()
.filter(|&(_, c)| c == '{' || c == '}')
.map(|(i, _)| {
fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })
})
.collect()
});
let msg = match &brace_spans {
Some(v) if v.len() == 1 => "panic message contains a brace",
_ => "panic message contains braces",
};
cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| {
let mut l = lint.build(msg);
l.note("this message is not used as a format string, but will be in a future Rust edition");
if expn.call_site.contains(arg.span) {
l.span_suggestion(
arg.span.shrink_to_lo(),
"add a \"{}\" format string to use the message literally",
"\"{}\", ".into(),
Applicability::MachineApplicable,
);
}
l.emit();
});
}
}
}
}
}
}

View file

@ -3,7 +3,7 @@
use crate::ty::{tls, TyCtxt}; use crate::ty::{tls, TyCtxt};
use rustc_span::{MultiSpan, Span}; use rustc_span::{MultiSpan, Span};
use std::fmt; use std::fmt;
use std::panic::Location; use std::panic::{panic_any, Location};
#[cold] #[cold]
#[inline(never)] #[inline(never)]
@ -32,7 +32,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
match (tcx, span) { match (tcx, span) {
(Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg), (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg),
(Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
(None, _) => panic!(msg), (None, _) => panic_any(msg),
} }
}); });
unreachable!(); unreachable!();

View file

@ -10,22 +10,23 @@ tests. `panic!` is closely tied with the `unwrap` method of both
`panic!` when they are set to [`None`] or [`Err`] variants. `panic!` when they are set to [`None`] or [`Err`] variants.
This macro is used to inject panic into a Rust thread, causing the thread to This macro is used to inject panic into a Rust thread, causing the thread to
panic entirely. Each thread's panic can be reaped as the [`Box`]`<`[`Any`]`>` type, panic entirely. This macro panics with a string and uses the [`format!`] syntax
and the single-argument form of the `panic!` macro will be the value which for building the message.
is transmitted.
Each thread's panic can be reaped as the [`Box`]`<`[`Any`]`>` type,
which contains either a `&str` or `String` for regular `panic!()` invocations.
To panic with a value of another other type, [`panic_any`] can be used.
[`Result`] enum is often a better solution for recovering from errors than [`Result`] enum is often a better solution for recovering from errors than
using the `panic!` macro. This macro should be used to avoid proceeding using using the `panic!` macro. This macro should be used to avoid proceeding using
incorrect values, such as from external sources. Detailed information about incorrect values, such as from external sources. Detailed information about
error handling is found in the [book]. error handling is found in the [book].
The multi-argument form of this macro panics with a string and has the
[`format!`] syntax for building a string.
See also the macro [`compile_error!`], for raising errors during compilation. See also the macro [`compile_error!`], for raising errors during compilation.
[ounwrap]: Option::unwrap [ounwrap]: Option::unwrap
[runwrap]: Result::unwrap [runwrap]: Result::unwrap
[`panic_any`]: ../std/panic/fn.panic_any.html
[`Box`]: ../std/boxed/struct.Box.html [`Box`]: ../std/boxed/struct.Box.html
[`Any`]: crate::any::Any [`Any`]: crate::any::Any
[`format!`]: ../std/macro.format.html [`format!`]: ../std/macro.format.html
@ -42,6 +43,6 @@ program with code `101`.
# #![allow(unreachable_code)] # #![allow(unreachable_code)]
panic!(); panic!();
panic!("this is a terrible mistake!"); panic!("this is a terrible mistake!");
panic!(4); // panic with the value of 4 to be collected elsewhere
panic!("this is a {} {message}", "fancy", message = "message"); panic!("this is a {} {message}", "fancy", message = "message");
std::panic::panic_any(4); // panic with the value of 4 to be collected elsewhere
``` ```

View file

@ -77,15 +77,15 @@ fn test_comparison_ops() {
for &(op, bs) in v.iter() { for &(op, bs) in v.iter() {
let s = format!("%{{1}}%{{2}}%{}%d", op); let s = format!("%{{1}}%{{2}}%{}%d", op);
let res = expand(s.as_bytes(), &[], &mut Variables::new()); let res = expand(s.as_bytes(), &[], &mut Variables::new());
assert!(res.is_ok(), res.unwrap_err()); assert!(res.is_ok(), "{}", res.unwrap_err());
assert_eq!(res.unwrap(), vec![b'0' + bs[0]]); assert_eq!(res.unwrap(), vec![b'0' + bs[0]]);
let s = format!("%{{1}}%{{1}}%{}%d", op); let s = format!("%{{1}}%{{1}}%{}%d", op);
let res = expand(s.as_bytes(), &[], &mut Variables::new()); let res = expand(s.as_bytes(), &[], &mut Variables::new());
assert!(res.is_ok(), res.unwrap_err()); assert!(res.is_ok(), "{}", res.unwrap_err());
assert_eq!(res.unwrap(), vec![b'0' + bs[1]]); assert_eq!(res.unwrap(), vec![b'0' + bs[1]]);
let s = format!("%{{2}}%{{1}}%{}%d", op); let s = format!("%{{2}}%{{1}}%{}%d", op);
let res = expand(s.as_bytes(), &[], &mut Variables::new()); let res = expand(s.as_bytes(), &[], &mut Variables::new());
assert!(res.is_ok(), res.unwrap_err()); assert!(res.is_ok(), "{}", res.unwrap_err());
assert_eq!(res.unwrap(), vec![b'0' + bs[2]]); assert_eq!(res.unwrap(), vec![b'0' + bs[2]]);
} }
} }
@ -95,13 +95,13 @@ fn test_conditionals() {
let mut vars = Variables::new(); let mut vars = Variables::new();
let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"; let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m";
let res = expand(s, &[Number(1)], &mut vars); let res = expand(s, &[Number(1)], &mut vars);
assert!(res.is_ok(), res.unwrap_err()); assert!(res.is_ok(), "{}", res.unwrap_err());
assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::<Vec<_>>()); assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::<Vec<_>>());
let res = expand(s, &[Number(8)], &mut vars); let res = expand(s, &[Number(8)], &mut vars);
assert!(res.is_ok(), res.unwrap_err()); assert!(res.is_ok(), "{}", res.unwrap_err());
assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::<Vec<_>>()); assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::<Vec<_>>());
let res = expand(s, &[Number(42)], &mut vars); let res = expand(s, &[Number(42)], &mut vars);
assert!(res.is_ok(), res.unwrap_err()); assert!(res.is_ok(), "{}", res.unwrap_err());
assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::<Vec<_>>()); assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::<Vec<_>>());
} }

View file

@ -199,7 +199,7 @@ fn test_should_panic_bad_message() {
fn test_should_panic_non_string_message_type() { fn test_should_panic_non_string_message_type() {
use crate::tests::TrFailedMsg; use crate::tests::TrFailedMsg;
fn f() { fn f() {
panic!(1i32); std::panic::panic_any(1i32);
} }
let expected = "foobar"; let expected = "foobar";
let failed_msg = format!( let failed_msg = format!(

View file

@ -50,7 +50,7 @@ fn test() {
.output().unwrap(); .output().unwrap();
assert!(child_output.status.success(), assert!(child_output.status.success(),
format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}", "child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
str::from_utf8(&child_output.stdout).unwrap(), str::from_utf8(&child_output.stdout).unwrap(),
str::from_utf8(&child_output.stderr).unwrap())); str::from_utf8(&child_output.stderr).unwrap());
} }

View file

@ -1,4 +1,5 @@
#![feature(const_panic)] #![feature(const_panic)]
#![allow(non_fmt_panic)]
#![crate_type = "lib"] #![crate_type = "lib"]
const MSG: &str = "hello"; const MSG: &str = "hello";

View file

@ -1,10 +1,10 @@
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:6:15 --> $DIR/const_panic.rs:7:15
| |
LL | const Z: () = std::panic!("cheese"); LL | const Z: () = std::panic!("cheese");
| --------------^^^^^^^^^^^^^^^^^^^^^- | --------------^^^^^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:6:15 | the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15
| |
= note: `#[deny(const_err)]` on by default = note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
@ -12,108 +12,108 @@ LL | const Z: () = std::panic!("cheese");
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:10:16 --> $DIR/const_panic.rs:11:16
| |
LL | const Z2: () = std::panic!(); LL | const Z2: () = std::panic!();
| ---------------^^^^^^^^^^^^^- | ---------------^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16 | the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:11:16
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:14:15 --> $DIR/const_panic.rs:15:15
| |
LL | const Y: () = std::unreachable!(); LL | const Y: () = std::unreachable!();
| --------------^^^^^^^^^^^^^^^^^^^- | --------------^^^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:14:15 | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:15:15
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:18:15 --> $DIR/const_panic.rs:19:15
| |
LL | const X: () = std::unimplemented!(); LL | const X: () = std::unimplemented!();
| --------------^^^^^^^^^^^^^^^^^^^^^- | --------------^^^^^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:18:15 | the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:19:15
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:22:15 --> $DIR/const_panic.rs:23:15
| |
LL | const W: () = std::panic!(MSG); LL | const W: () = std::panic!(MSG);
| --------------^^^^^^^^^^^^^^^^- | --------------^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'hello', $DIR/const_panic.rs:22:15 | the evaluated program panicked at 'hello', $DIR/const_panic.rs:23:15
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:26:20 --> $DIR/const_panic.rs:27:20
| |
LL | const Z_CORE: () = core::panic!("cheese"); LL | const Z_CORE: () = core::panic!("cheese");
| -------------------^^^^^^^^^^^^^^^^^^^^^^- | -------------------^^^^^^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:26:20 | the evaluated program panicked at 'cheese', $DIR/const_panic.rs:27:20
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:30:21 --> $DIR/const_panic.rs:31:21
| |
LL | const Z2_CORE: () = core::panic!(); LL | const Z2_CORE: () = core::panic!();
| --------------------^^^^^^^^^^^^^^- | --------------------^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:30:21 | the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:31:21
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:34:20 --> $DIR/const_panic.rs:35:20
| |
LL | const Y_CORE: () = core::unreachable!(); LL | const Y_CORE: () = core::unreachable!();
| -------------------^^^^^^^^^^^^^^^^^^^^- | -------------------^^^^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:34:20 | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:35:20
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:38:20 --> $DIR/const_panic.rs:39:20
| |
LL | const X_CORE: () = core::unimplemented!(); LL | const X_CORE: () = core::unimplemented!();
| -------------------^^^^^^^^^^^^^^^^^^^^^^- | -------------------^^^^^^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:38:20 | the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:39:20
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: any use of this value will cause an error error: any use of this value will cause an error
--> $DIR/const_panic.rs:42:20 --> $DIR/const_panic.rs:43:20
| |
LL | const W_CORE: () = core::panic!(MSG); LL | const W_CORE: () = core::panic!(MSG);
| -------------------^^^^^^^^^^^^^^^^^- | -------------------^^^^^^^^^^^^^^^^^-
| | | |
| the evaluated program panicked at 'hello', $DIR/const_panic.rs:42:20 | the evaluated program panicked at 'hello', $DIR/const_panic.rs:43:20
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>

View file

@ -82,7 +82,7 @@ impl Allocator {
self.cur_ops.set(self.cur_ops.get() + 1); self.cur_ops.set(self.cur_ops.get() + 1);
if self.cur_ops.get() == self.failing_op { if self.cur_ops.get() == self.failing_op {
panic!(InjectedFailure); panic::panic_any(InjectedFailure);
} }
} }
} }

View file

@ -46,7 +46,7 @@ impl Allocator {
self.cur_ops.set(self.cur_ops.get() + 1); self.cur_ops.set(self.cur_ops.get() + 1);
if self.cur_ops.get() == self.failing_op { if self.cur_ops.get() == self.failing_op {
panic!(InjectedFailure); panic::panic_any(InjectedFailure);
} }
let mut data = self.data.borrow_mut(); let mut data = self.data.borrow_mut();
@ -67,7 +67,7 @@ impl<'a> Drop for Ptr<'a> {
self.1.cur_ops.set(self.1.cur_ops.get() + 1); self.1.cur_ops.set(self.1.cur_ops.get() + 1);
if self.1.cur_ops.get() == self.1.failing_op { if self.1.cur_ops.get() == self.1.failing_op {
panic!(InjectedFailure); panic::panic_any(InjectedFailure);
} }
} }
} }

View file

@ -31,7 +31,7 @@ fn panic_with_single_argument_does_not_get_formatted() {
// RFC #2795 suggests that this may need to change so that captured arguments are formatted. // RFC #2795 suggests that this may need to change so that captured arguments are formatted.
// For stability reasons this will need to part of an edition change. // For stability reasons this will need to part of an edition change.
#[allow(panic_fmt)] #[allow(non_fmt_panic)]
let msg = std::panic::catch_unwind(|| { let msg = std::panic::catch_unwind(|| {
panic!("{foo}"); panic!("{foo}");
}).unwrap_err(); }).unwrap_err();

View file

@ -2,6 +2,8 @@
// error-pattern:panicked at 'test-assert-owned' // error-pattern:panicked at 'test-assert-owned'
// ignore-emscripten no processes // ignore-emscripten no processes
#![allow(non_fmt_panic)]
fn main() { fn main() {
assert!(false, "test-assert-owned".to_string()); assert!(false, "test-assert-owned".to_string());
} }

View file

@ -57,7 +57,7 @@ fn writeln_1arg() {
// //
// (Example: Issue #48042) // (Example: Issue #48042)
#[test] #[test]
#[allow(panic_fmt)] #[allow(non_fmt_panic)]
fn to_format_or_not_to_format() { fn to_format_or_not_to_format() {
// ("{}" is the easiest string to test because if this gets // ("{}" is the easiest string to test because if this gets
// sent to format_args!, it'll simply fail to compile. // sent to format_args!, it'll simply fail to compile.

View file

@ -38,7 +38,7 @@ fn main() {
assert_eq!(get(), vec![0, 2, 3, 1]); assert_eq!(get(), vec![0, 2, 3, 1]);
let _ = std::panic::catch_unwind(|| { let _ = std::panic::catch_unwind(|| {
(d(4), &d(5), d(6), &d(7), panic!(InjectedFailure)); (d(4), &d(5), d(6), &d(7), panic::panic_any(InjectedFailure));
}); });
// here, the temporaries (5/7) live until the end of the // here, the temporaries (5/7) live until the end of the

View file

@ -13,19 +13,27 @@ fn main() {
core::panic!("Hello {}"); //~ WARN panic message contains an unused formatting placeholder core::panic!("Hello {}"); //~ WARN panic message contains an unused formatting placeholder
assert!(false, "{:03x} {test} bla"); assert!(false, "{:03x} {test} bla");
//~^ WARN panic message contains unused formatting placeholders //~^ WARN panic message contains unused formatting placeholders
assert!(false, S);
//~^ WARN panic message is not a string literal
debug_assert!(false, "{{}} bla"); //~ WARN panic message contains braces debug_assert!(false, "{{}} bla"); //~ WARN panic message contains braces
panic!(C); // No warning (yet) panic!(C); //~ WARN panic message is not a string literal
panic!(S); // No warning (yet) panic!(S); //~ WARN panic message is not a string literal
std::panic!(123); //~ WARN panic message is not a string literal
core::panic!(&*"abc"); //~ WARN panic message is not a string literal
panic!(concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder panic!(concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder
panic!(concat!("{", "{")); //~ WARN panic message contains braces panic!(concat!("{", "{")); //~ WARN panic message contains braces
fancy_panic::fancy_panic!("test {} 123"); fancy_panic::fancy_panic!("test {} 123");
//~^ WARN panic message contains an unused formatting placeholder //~^ WARN panic message contains an unused formatting placeholder
fancy_panic::fancy_panic!(S);
//~^ WARN panic message is not a string literal
// Check that the lint only triggers for std::panic and core::panic, // Check that the lint only triggers for std::panic and core::panic,
// not any panic macro: // not any panic macro:
macro_rules! panic { macro_rules! panic {
($e:expr) => (); ($e:expr) => ();
} }
panic!("{}"); // OK panic!("{}"); // OK
panic!(S); // OK
} }

View file

@ -1,35 +1,35 @@
warning: panic message contains a brace warning: panic message contains a brace
--> $DIR/panic-brace.rs:11:29 --> $DIR/non-fmt-panic.rs:11:29
| |
LL | panic!("here's a brace: {"); LL | panic!("here's a brace: {");
| ^ | ^
| |
= note: `#[warn(panic_fmt)]` on by default = note: `#[warn(non_fmt_panic)]` on by default
= note: this message is not used as a format string, but will be in a future Rust edition = note: this message is not used as a format string, but will be in Rust 2021
help: add a "{}" format string to use the message literally help: add a "{}" format string to use the message literally
| |
LL | panic!("{}", "here's a brace: {"); LL | panic!("{}", "here's a brace: {");
| ^^^^^ | ^^^^^
warning: panic message contains a brace warning: panic message contains a brace
--> $DIR/panic-brace.rs:12:31 --> $DIR/non-fmt-panic.rs:12:31
| |
LL | std::panic!("another one: }"); LL | std::panic!("another one: }");
| ^ | ^
| |
= note: this message is not used as a format string, but will be in a future Rust edition = note: this message is not used as a format string, but will be in Rust 2021
help: add a "{}" format string to use the message literally help: add a "{}" format string to use the message literally
| |
LL | std::panic!("{}", "another one: }"); LL | std::panic!("{}", "another one: }");
| ^^^^^ | ^^^^^
warning: panic message contains an unused formatting placeholder warning: panic message contains an unused formatting placeholder
--> $DIR/panic-brace.rs:13:25 --> $DIR/non-fmt-panic.rs:13:25
| |
LL | core::panic!("Hello {}"); LL | core::panic!("Hello {}");
| ^^ | ^^
| |
= note: this message is not used as a format string when given without arguments, but will be in a future Rust edition = note: this message is not used as a format string when given without arguments, but will be in Rust 2021
help: add the missing argument help: add the missing argument
| |
LL | core::panic!("Hello {}", ...); LL | core::panic!("Hello {}", ...);
@ -40,12 +40,12 @@ LL | core::panic!("{}", "Hello {}");
| ^^^^^ | ^^^^^
warning: panic message contains unused formatting placeholders warning: panic message contains unused formatting placeholders
--> $DIR/panic-brace.rs:14:21 --> $DIR/non-fmt-panic.rs:14:21
| |
LL | assert!(false, "{:03x} {test} bla"); LL | assert!(false, "{:03x} {test} bla");
| ^^^^^^ ^^^^^^ | ^^^^^^ ^^^^^^
| |
= note: this message is not used as a format string when given without arguments, but will be in a future Rust edition = note: this message is not used as a format string when given without arguments, but will be in Rust 2021
help: add the missing arguments help: add the missing arguments
| |
LL | assert!(false, "{:03x} {test} bla", ...); LL | assert!(false, "{:03x} {test} bla", ...);
@ -55,25 +55,97 @@ help: or add a "{}" format string to use the message literally
LL | assert!(false, "{}", "{:03x} {test} bla"); LL | assert!(false, "{}", "{:03x} {test} bla");
| ^^^^^ | ^^^^^
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:16:20
|
LL | assert!(false, S);
| ^
|
= note: this is no longer accepted in Rust 2021
help: add a "{}" format string to Display the message
|
LL | assert!(false, "{}", S);
| ^^^^^
warning: panic message contains braces warning: panic message contains braces
--> $DIR/panic-brace.rs:16:27 --> $DIR/non-fmt-panic.rs:18:27
| |
LL | debug_assert!(false, "{{}} bla"); LL | debug_assert!(false, "{{}} bla");
| ^^^^ | ^^^^
| |
= note: this message is not used as a format string, but will be in a future Rust edition = note: this message is not used as a format string, but will be in Rust 2021
help: add a "{}" format string to use the message literally help: add a "{}" format string to use the message literally
| |
LL | debug_assert!(false, "{}", "{{}} bla"); LL | debug_assert!(false, "{}", "{{}} bla");
| ^^^^^ | ^^^^^
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:19:12
|
LL | panic!(C);
| ^
|
= note: this is no longer accepted in Rust 2021
help: add a "{}" format string to Display the message
|
LL | panic!("{}", C);
| ^^^^^
help: or use std::panic::panic_any instead
|
LL | std::panic::panic_any(C);
| ^^^^^^^^^^^^^^^^^^^^^^
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:20:12
|
LL | panic!(S);
| ^
|
= note: this is no longer accepted in Rust 2021
help: add a "{}" format string to Display the message
|
LL | panic!("{}", S);
| ^^^^^
help: or use std::panic::panic_any instead
|
LL | std::panic::panic_any(S);
| ^^^^^^^^^^^^^^^^^^^^^^
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:21:17
|
LL | std::panic!(123);
| ^^^
|
= note: this is no longer accepted in Rust 2021
help: add a "{}" format string to Display the message
|
LL | std::panic!("{}", 123);
| ^^^^^
help: or use std::panic::panic_any instead
|
LL | std::panic::panic_any(123);
| ^^^^^^^^^^^^^^^^^^^^^^
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:22:18
|
LL | core::panic!(&*"abc");
| ^^^^^^^
|
= note: this is no longer accepted in Rust 2021
help: add a "{}" format string to Display the message
|
LL | core::panic!("{}", &*"abc");
| ^^^^^
warning: panic message contains an unused formatting placeholder warning: panic message contains an unused formatting placeholder
--> $DIR/panic-brace.rs:19:12 --> $DIR/non-fmt-panic.rs:23:12
| |
LL | panic!(concat!("{", "}")); LL | panic!(concat!("{", "}"));
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
| |
= note: this message is not used as a format string when given without arguments, but will be in a future Rust edition = note: this message is not used as a format string when given without arguments, but will be in Rust 2021
help: add the missing argument help: add the missing argument
| |
LL | panic!(concat!("{", "}"), ...); LL | panic!(concat!("{", "}"), ...);
@ -84,24 +156,32 @@ LL | panic!("{}", concat!("{", "}"));
| ^^^^^ | ^^^^^
warning: panic message contains braces warning: panic message contains braces
--> $DIR/panic-brace.rs:20:5 --> $DIR/non-fmt-panic.rs:24:5
| |
LL | panic!(concat!("{", "{")); LL | panic!(concat!("{", "{"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this message is not used as a format string, but will be in a future Rust edition = note: this message is not used as a format string, but will be in Rust 2021
help: add a "{}" format string to use the message literally help: add a "{}" format string to use the message literally
| |
LL | panic!("{}", concat!("{", "{")); LL | panic!("{}", concat!("{", "{"));
| ^^^^^ | ^^^^^
warning: panic message contains an unused formatting placeholder warning: panic message contains an unused formatting placeholder
--> $DIR/panic-brace.rs:22:37 --> $DIR/non-fmt-panic.rs:26:37
| |
LL | fancy_panic::fancy_panic!("test {} 123"); LL | fancy_panic::fancy_panic!("test {} 123");
| ^^ | ^^
| |
= note: this message is not used as a format string when given without arguments, but will be in a future Rust edition = note: this message is not used as a format string when given without arguments, but will be in Rust 2021
warning: 8 warnings emitted warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:29:31
|
LL | fancy_panic::fancy_panic!(S);
| ^
|
= note: this is no longer accepted in Rust 2021
warning: 14 warnings emitted

View file

@ -1,5 +1,6 @@
#![allow(unused_assignments)] #![allow(unused_assignments)]
#![allow(unused_variables)] #![allow(unused_variables)]
#![allow(non_fmt_panic)]
// run-fail // run-fail
// error-pattern:wooooo // error-pattern:wooooo

View file

@ -2,6 +2,8 @@
// error-pattern:panicked at 'Box<Any>' // error-pattern:panicked at 'Box<Any>'
// ignore-emscripten no processes // ignore-emscripten no processes
#![allow(non_fmt_panic)]
fn main() { fn main() {
panic!(Box::new(612_i64)); panic!(Box::new(612_i64));
} }

View file

@ -3,6 +3,7 @@
// ignore-emscripten no processes // ignore-emscripten no processes
#![feature(box_syntax)] #![feature(box_syntax)]
#![allow(non_fmt_panic)]
fn main() { fn main() {
panic!(box 413 as Box<dyn std::any::Any + Send>); panic!(box 413 as Box<dyn std::any::Any + Send>);

View file

@ -5,7 +5,7 @@
// ignore-emscripten no processes // ignore-emscripten no processes
fn main() { fn main() {
panic!({ panic!("{}", {
while true { while true {
panic!("giraffe") panic!("giraffe")
} }

View file

@ -2183,7 +2183,7 @@ fn lint_expect_fun_call(
span_replace_word, span_replace_word,
&format!("use of `{}` followed by a function call", name), &format!("use of `{}` followed by a function call", name),
"try this", "try this",
format!("unwrap_or_else({} {{ panic!({}) }})", closure_args, arg_root_snippet), format!("unwrap_or_else({} {{ panic!(\"{{}}\", {}) }})", closure_args, arg_root_snippet),
applicability, applicability,
); );
} }

View file

@ -9,14 +9,12 @@ fn test_missing_tests() {
if !missing_files.is_empty() { if !missing_files.is_empty() {
assert!( assert!(
false, false,
format!( "Didn't see a test file for the following files:\n\n{}\n",
"Didn't see a test file for the following files:\n\n{}\n", missing_files
missing_files .iter()
.iter() .map(|s| format!("\t{}", s))
.map(|s| format!("\t{}", s)) .collect::<Vec<_>>()
.collect::<Vec<_>>() .join("\n")
.join("\n")
)
); );
} }
} }

View file

@ -1,3 +1,5 @@
#![allow(non_fmt_panic)]
macro_rules! assert_const { macro_rules! assert_const {
($len:expr) => { ($len:expr) => {
assert!($len > 0); assert!($len > 0);

View file

@ -1,5 +1,5 @@
error: `assert!(true)` will be optimized out by the compiler error: `assert!(true)` will be optimized out by the compiler
--> $DIR/assertions_on_constants.rs:9:5 --> $DIR/assertions_on_constants.rs:11:5
| |
LL | assert!(true); LL | assert!(true);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -9,7 +9,7 @@ LL | assert!(true);
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(false)` should probably be replaced error: `assert!(false)` should probably be replaced
--> $DIR/assertions_on_constants.rs:10:5 --> $DIR/assertions_on_constants.rs:12:5
| |
LL | assert!(false); LL | assert!(false);
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
@ -18,7 +18,7 @@ LL | assert!(false);
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(true)` will be optimized out by the compiler error: `assert!(true)` will be optimized out by the compiler
--> $DIR/assertions_on_constants.rs:11:5 --> $DIR/assertions_on_constants.rs:13:5
| |
LL | assert!(true, "true message"); LL | assert!(true, "true message");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -27,7 +27,7 @@ LL | assert!(true, "true message");
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(false, "false message")` should probably be replaced error: `assert!(false, "false message")` should probably be replaced
--> $DIR/assertions_on_constants.rs:12:5 --> $DIR/assertions_on_constants.rs:14:5
| |
LL | assert!(false, "false message"); LL | assert!(false, "false message");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -36,7 +36,7 @@ LL | assert!(false, "false message");
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(false, msg.to_uppercase())` should probably be replaced error: `assert!(false, msg.to_uppercase())` should probably be replaced
--> $DIR/assertions_on_constants.rs:15:5 --> $DIR/assertions_on_constants.rs:17:5
| |
LL | assert!(false, msg.to_uppercase()); LL | assert!(false, msg.to_uppercase());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -45,7 +45,7 @@ LL | assert!(false, msg.to_uppercase());
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(true)` will be optimized out by the compiler error: `assert!(true)` will be optimized out by the compiler
--> $DIR/assertions_on_constants.rs:18:5 --> $DIR/assertions_on_constants.rs:20:5
| |
LL | assert!(B); LL | assert!(B);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
@ -54,7 +54,7 @@ LL | assert!(B);
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(false)` should probably be replaced error: `assert!(false)` should probably be replaced
--> $DIR/assertions_on_constants.rs:21:5 --> $DIR/assertions_on_constants.rs:23:5
| |
LL | assert!(C); LL | assert!(C);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
@ -63,7 +63,7 @@ LL | assert!(C);
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(false, "C message")` should probably be replaced error: `assert!(false, "C message")` should probably be replaced
--> $DIR/assertions_on_constants.rs:22:5 --> $DIR/assertions_on_constants.rs:24:5
| |
LL | assert!(C, "C message"); LL | assert!(C, "C message");
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@ -72,7 +72,7 @@ LL | assert!(C, "C message");
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: `debug_assert!(true)` will be optimized out by the compiler error: `debug_assert!(true)` will be optimized out by the compiler
--> $DIR/assertions_on_constants.rs:24:5 --> $DIR/assertions_on_constants.rs:26:5
| |
LL | debug_assert!(true); LL | debug_assert!(true);
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^

View file

@ -74,12 +74,12 @@ fn main() {
"foo" "foo"
} }
Some("foo").unwrap_or_else(|| { panic!(get_string()) }); Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) });
Some("foo").unwrap_or_else(|| { panic!(get_string()) }); Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) });
Some("foo").unwrap_or_else(|| { panic!(get_string()) }); Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) });
Some("foo").unwrap_or_else(|| { panic!(get_static_str()) }); Some("foo").unwrap_or_else(|| { panic!("{}", get_static_str()) });
Some("foo").unwrap_or_else(|| { panic!(get_non_static_str(&0).to_string()) }); Some("foo").unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) });
} }
//Issue #3839 //Issue #3839

View file

@ -34,31 +34,31 @@ error: use of `expect` followed by a function call
--> $DIR/expect_fun_call.rs:77:21 --> $DIR/expect_fun_call.rs:77:21
| |
LL | Some("foo").expect(&get_string()); LL | Some("foo").expect(&get_string());
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_string()) })` | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call error: use of `expect` followed by a function call
--> $DIR/expect_fun_call.rs:78:21 --> $DIR/expect_fun_call.rs:78:21
| |
LL | Some("foo").expect(get_string().as_ref()); LL | Some("foo").expect(get_string().as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_string()) })` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call error: use of `expect` followed by a function call
--> $DIR/expect_fun_call.rs:79:21 --> $DIR/expect_fun_call.rs:79:21
| |
LL | Some("foo").expect(get_string().as_str()); LL | Some("foo").expect(get_string().as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_string()) })` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call error: use of `expect` followed by a function call
--> $DIR/expect_fun_call.rs:81:21 --> $DIR/expect_fun_call.rs:81:21
| |
LL | Some("foo").expect(get_static_str()); LL | Some("foo").expect(get_static_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_static_str()) })` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })`
error: use of `expect` followed by a function call error: use of `expect` followed by a function call
--> $DIR/expect_fun_call.rs:82:21 --> $DIR/expect_fun_call.rs:82:21
| |
LL | Some("foo").expect(get_non_static_str(&0)); LL | Some("foo").expect(get_non_static_str(&0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!(get_non_static_str(&0).to_string()) })` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })`
error: use of `expect` followed by a function call error: use of `expect` followed by a function call
--> $DIR/expect_fun_call.rs:86:16 --> $DIR/expect_fun_call.rs:86:16

View file

@ -36,7 +36,7 @@ impl From<Option<String>> for Invalid {
fn from(s: Option<String>) -> Invalid { fn from(s: Option<String>) -> Invalid {
let s = s.unwrap(); let s = s.unwrap();
if !s.is_empty() { if !s.is_empty() {
panic!(42); panic!("42");
} else if s.parse::<u32>().unwrap() != 42 { } else if s.parse::<u32>().unwrap() != 42 {
panic!("{:?}", s); panic!("{:?}", s);
} }

View file

@ -59,8 +59,8 @@ note: potential failure(s)
LL | let s = s.unwrap(); LL | let s = s.unwrap();
| ^^^^^^^^^^ | ^^^^^^^^^^
LL | if !s.is_empty() { LL | if !s.is_empty() {
LL | panic!(42); LL | panic!("42");
| ^^^^^^^^^^^ | ^^^^^^^^^^^^^
LL | } else if s.parse::<u32>().unwrap() != 42 { LL | } else if s.parse::<u32>().unwrap() != 42 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
LL | panic!("{:?}", s); LL | panic!("{:?}", s);