Improve suggestion for panic!(format!(..)).
This commit is contained in:
parent
1abc1e2a43
commit
a428ab17ab
3 changed files with 32 additions and 1 deletions
|
@ -72,18 +72,38 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||||
// Find the span of the argument to `panic!()`, before expansion in the
|
// Find the span of the argument to `panic!()`, before expansion in the
|
||||||
// case of `panic!(some_macro!())`.
|
// case of `panic!(some_macro!())`.
|
||||||
let mut arg_span = arg.span;
|
let mut arg_span = arg.span;
|
||||||
|
let mut arg_macro = None;
|
||||||
while !span.contains(arg_span) {
|
while !span.contains(arg_span) {
|
||||||
let expn = arg_span.ctxt().outer_expn_data();
|
let expn = arg_span.ctxt().outer_expn_data();
|
||||||
if expn.is_root() {
|
if expn.is_root() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
arg_macro = expn.macro_def_id;
|
||||||
arg_span = expn.call_site;
|
arg_span = expn.call_site;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.struct_span_lint(NON_FMT_PANIC, arg_span, |lint| {
|
cx.struct_span_lint(NON_FMT_PANIC, arg_span, |lint| {
|
||||||
let mut l = lint.build("panic message is not a string literal");
|
let mut l = lint.build("panic message is not a string literal");
|
||||||
l.note("this is no longer accepted in Rust 2021");
|
l.note("this is no longer accepted in Rust 2021");
|
||||||
if span.contains(arg_span) {
|
if !span.contains(arg_span) {
|
||||||
|
// No clue where this argument is coming from.
|
||||||
|
l.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
|
||||||
|
// A case of `panic!(format!(..))`.
|
||||||
|
l.note("the panic!() macro supports formatting, so there's no need for the format!() macro here");
|
||||||
|
if let Some(inner) = find_inner_span(cx, arg_span) {
|
||||||
|
l.multipart_suggestion(
|
||||||
|
"remove the `format!(..)` macro call",
|
||||||
|
vec![
|
||||||
|
(arg_span.until(inner), "".into()),
|
||||||
|
(inner.between(arg_span.shrink_to_hi()), "".into()),
|
||||||
|
],
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
l.span_suggestion_verbose(
|
l.span_suggestion_verbose(
|
||||||
arg_span.shrink_to_lo(),
|
arg_span.shrink_to_lo(),
|
||||||
"add a \"{}\" format string to Display the message",
|
"add a \"{}\" format string to Display the message",
|
||||||
|
@ -186,6 +206,15 @@ fn check_panic_str<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given the span of `some_macro!(args)`, gives the span of `args`.
|
||||||
|
fn find_inner_span<'tcx>(cx: &LateContext<'tcx>, span: Span) -> Option<Span> {
|
||||||
|
let snippet = cx.sess().parse_sess.source_map().span_to_snippet(span).ok()?;
|
||||||
|
Some(span.from_inner(InnerSpan {
|
||||||
|
start: snippet.find(&['(', '{', '['][..])? + 1,
|
||||||
|
end: snippet.rfind(&[')', '}', ']'][..])?,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol) {
|
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 expn = f.span.ctxt().outer_expn_data();
|
||||||
|
|
||||||
|
|
|
@ -554,6 +554,7 @@ symbols! {
|
||||||
format_args,
|
format_args,
|
||||||
format_args_capture,
|
format_args_capture,
|
||||||
format_args_nl,
|
format_args_nl,
|
||||||
|
format_macro,
|
||||||
freeze,
|
freeze,
|
||||||
freg,
|
freg,
|
||||||
frem_fast,
|
frem_fast,
|
||||||
|
|
|
@ -107,6 +107,7 @@ macro_rules! vec {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_diagnostic_item = "format_macro"]
|
||||||
macro_rules! format {
|
macro_rules! format {
|
||||||
($($arg:tt)*) => {{
|
($($arg:tt)*) => {{
|
||||||
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
|
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue