@@ -93,12 +93,12 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
9393 if arg_macro. map_or ( false , |id| cx. tcx . is_diagnostic_item ( sym:: format_macro, id) ) {
9494 // A case of `panic!(format!(..))`.
9595 l. note ( "the panic!() macro supports formatting, so there's no need for the format!() macro here" ) ;
96- if let Some ( inner ) = find_inner_span ( cx, arg_span) {
96+ if let Some ( ( open , close , _ ) ) = find_delimiters ( cx, arg_span) {
9797 l. multipart_suggestion (
9898 "remove the `format!(..)` macro call" ,
9999 vec ! [
100- ( arg_span. until( inner ) , "" . into( ) ) ,
101- ( inner . between ( arg_span. shrink_to_hi( ) ) , "" . into( ) ) ,
100+ ( arg_span. until( open . shrink_to_hi ( ) ) , "" . into( ) ) ,
101+ ( close . until ( arg_span. shrink_to_hi( ) ) , "" . into( ) ) ,
102102 ] ,
103103 Applicability :: MachineApplicable ,
104104 ) ;
@@ -111,12 +111,20 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
111111 Applicability :: MaybeIncorrect ,
112112 ) ;
113113 if panic == sym:: std_panic_macro {
114- l. span_suggestion_verbose (
115- span. until ( arg_span) ,
116- "or use std::panic::panic_any instead" ,
117- "std::panic::panic_any(" . into ( ) ,
118- Applicability :: MachineApplicable ,
119- ) ;
114+ if let Some ( ( open, close, del) ) = find_delimiters ( cx, span) {
115+ l. multipart_suggestion (
116+ "or use std::panic::panic_any instead" ,
117+ if del == '(' {
118+ vec ! [ ( span. until( open) , "std::panic::panic_any" . into( ) ) ]
119+ } else {
120+ vec ! [
121+ ( span. until( open. shrink_to_hi( ) ) , "std::panic::panic_any(" . into( ) ) ,
122+ ( close, ")" . into( ) ) ,
123+ ]
124+ } ,
125+ Applicability :: MachineApplicable ,
126+ ) ;
127+ }
120128 }
121129 }
122130 l. emit ( ) ;
@@ -206,13 +214,23 @@ fn check_panic_str<'tcx>(
206214 }
207215}
208216
209- /// Given the span of `some_macro!(args)`, gives the span of `args`.
210- fn find_inner_span < ' tcx > ( cx : & LateContext < ' tcx > , span : Span ) -> Option < Span > {
217+ /// Given the span of `some_macro!(args);`, gives the span of `(` and `)`,
218+ /// and the type of (opening) delimiter used.
219+ fn find_delimiters < ' tcx > ( cx : & LateContext < ' tcx > , span : Span ) -> Option < ( Span , Span , char ) > {
211220 let snippet = cx. sess ( ) . parse_sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ?;
212- Some ( span. from_inner ( InnerSpan {
213- start : snippet. find ( & [ '(' , '{' , '[' ] [ ..] ) ? + 1 ,
214- end : snippet. rfind ( & [ ')' , '}' , ']' ] [ ..] ) ?,
215- } ) )
221+ let ( open, open_ch) = snippet. char_indices ( ) . find ( |& ( _, c) | "([{" . contains ( c) ) ?;
222+ let close = snippet. rfind ( |c| ")]}" . contains ( c) ) ?;
223+ Some ( (
224+ span. from_inner ( InnerSpan {
225+ start : open,
226+ end : open + 1 ,
227+ } ) ,
228+ span. from_inner ( InnerSpan {
229+ start : close,
230+ end : close + 1 ,
231+ } ) ,
232+ open_ch,
233+ ) )
216234}
217235
218236fn panic_call < ' tcx > ( cx : & LateContext < ' tcx > , f : & ' tcx hir:: Expr < ' tcx > ) -> ( Span , Symbol ) {
0 commit comments