mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
Improve suggestion for panic!(format!(..)).
This commit is contained in:
parent
1abc1e2a43
commit
a428ab17ab
@ -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
|
||||
// case of `panic!(some_macro!())`.
|
||||
let mut arg_span = arg.span;
|
||||
let mut arg_macro = None;
|
||||
while !span.contains(arg_span) {
|
||||
let expn = arg_span.ctxt().outer_expn_data();
|
||||
if expn.is_root() {
|
||||
break;
|
||||
}
|
||||
arg_macro = expn.macro_def_id;
|
||||
arg_span = expn.call_site;
|
||||
}
|
||||
|
||||
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) {
|
||||
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(
|
||||
arg_span.shrink_to_lo(),
|
||||
"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) {
|
||||
let mut expn = f.span.ctxt().outer_expn_data();
|
||||
|
||||
|
@ -554,6 +554,7 @@ symbols! {
|
||||
format_args,
|
||||
format_args_capture,
|
||||
format_args_nl,
|
||||
format_macro,
|
||||
freeze,
|
||||
freg,
|
||||
frem_fast,
|
||||
|
@ -107,6 +107,7 @@ macro_rules! vec {
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "format_macro"]
|
||||
macro_rules! format {
|
||||
($($arg:tt)*) => {{
|
||||
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
|
||||
|
Loading…
Reference in New Issue
Block a user