@@ -95,7 +95,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
9595 let mut l = lint. build ( "panic message is not a string literal" ) ;
9696 l. note ( "this usage of panic!() is deprecated; it will be a hard error in Rust 2021" ) ;
9797 l. note ( "for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>" ) ;
98- if !span . contains ( arg_span) {
98+ if !is_arg_inside_call ( arg_span, span ) {
9999 // No clue where this argument is coming from.
100100 l. emit ( ) ;
101101 return ;
@@ -180,7 +180,7 @@ fn check_panic_str<'tcx>(
180180 _ => "panic message contains unused formatting placeholders" ,
181181 } ) ;
182182 l. note ( "this message is not used as a format string when given without arguments, but will be in Rust 2021" ) ;
183- if span . contains ( arg. span ) {
183+ if is_arg_inside_call ( arg. span , span) {
184184 l. span_suggestion (
185185 arg. span . shrink_to_hi ( ) ,
186186 & format ! ( "add the missing argument{}" , pluralize!( n_arguments) ) ,
@@ -211,7 +211,7 @@ fn check_panic_str<'tcx>(
211211 cx. struct_span_lint ( NON_FMT_PANICS , brace_spans. unwrap_or_else ( || vec ! [ span] ) , |lint| {
212212 let mut l = lint. build ( msg) ;
213213 l. note ( "this message is not used as a format string, but will be in Rust 2021" ) ;
214- if span . contains ( arg. span ) {
214+ if is_arg_inside_call ( arg. span , span) {
215215 l. span_suggestion (
216216 arg. span . shrink_to_lo ( ) ,
217217 "add a \" {}\" format string to use the message literally" ,
@@ -259,3 +259,11 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span,
259259 if let hygiene:: ExpnKind :: Macro ( _, symbol) = expn. kind { symbol } else { sym:: panic } ;
260260 ( expn. call_site , panic_macro, macro_symbol. as_str ( ) )
261261}
262+
263+ fn is_arg_inside_call ( arg : Span , call : Span ) -> bool {
264+ // We only add suggestions if the argument we're looking at appears inside the
265+ // panic call in the source file, to avoid invalid suggestions when macros are involved.
266+ // We specifically check for the spans to not be identical, as that happens sometimes when
267+ // proc_macros lie about spans and apply the same span to all the tokens they produce.
268+ call. contains ( arg) && !call. source_equal ( & arg)
269+ }
0 commit comments