@@ -120,8 +120,8 @@ fn tester(fn_arg: i32) {
120120 println!("{local_i32:width$.prec$}");
121121 println!("{width:width$.prec$}");
122122 println!("{}", format!("{local_i32}"));
123- my_println!("{}", local_i32 );
124- my_println_args!("{}", local_i32 );
123+ my_println!("{local_i32}" );
124+ my_println_args!("{local_i32}" );
125125
126126 // these should NOT be modified by the lint
127127 println!(concat!("nope ", "{}"), local_i32);
@@ -159,10 +159,6 @@ fn tester(fn_arg: i32) {
159159 }
160160}
161161
162- fn main() {
163- tester(42);
164- }
165-
166162#[clippy::msrv = "1.57"]
167163fn _under_msrv() {
168164 let local_i32 = 1;
@@ -174,3 +170,94 @@ fn _meets_msrv() {
174170 let local_i32 = 1;
175171 println!("expand='{local_i32}'");
176172}
173+
174+ macro_rules! _internal {
175+ ($($args:tt)*) => {
176+ println!("{}", format_args!($($args)*))
177+ };
178+ }
179+
180+ macro_rules! my_println2 {
181+ ($target:expr, $($args:tt)+) => {{
182+ if $target {
183+ _internal!($($args)+)
184+ }
185+ }};
186+ }
187+
188+ macro_rules! my_println2_args {
189+ ($target:expr, $($args:tt)+) => {{
190+ if $target {
191+ _internal!("foo: {}", format_args!($($args)+))
192+ }
193+ }};
194+ }
195+
196+ macro_rules! my_concat {
197+ ($fmt:literal $(, $e:expr)*) => {
198+ println!(concat!("ERROR: ", $fmt), $($e,)*)
199+ }
200+ }
201+
202+ macro_rules! my_good_macro {
203+ ($fmt:literal $(, $e:expr)* $(,)?) => {
204+ println!($fmt $(, $e)*)
205+ }
206+ }
207+
208+ macro_rules! my_bad_macro {
209+ ($fmt:literal, $($e:expr),*) => {
210+ println!($fmt, $($e,)*)
211+ }
212+ }
213+
214+ macro_rules! my_bad_macro2 {
215+ ($fmt:literal) => {
216+ let s = $fmt.clone();
217+ println!("{}", s);
218+ };
219+ ($fmt:literal, $($e:expr)+) => {
220+ println!($fmt, $($e,)*)
221+ };
222+ }
223+
224+ // This abomination was suggested by @Alexendoo, may the Rust gods have mercy on their soul...
225+ // https://github.com/rust-lang/rust-clippy/pull/9948#issuecomment-1327965962
226+ macro_rules! used_twice {
227+ (
228+ large = $large:literal,
229+ small = $small:literal,
230+ $val:expr,
231+ ) => {
232+ if $val < 5 {
233+ println!($small, $val);
234+ } else {
235+ println!($large, $val);
236+ }
237+ };
238+ }
239+
240+ fn tester2() {
241+ let local_i32 = 1;
242+ my_println2_args!(true, "{local_i32}");
243+ my_println2!(true, "{local_i32}");
244+ my_concat!("{}", local_i32);
245+ my_good_macro!("{local_i32}");
246+ my_good_macro!("{local_i32}",);
247+
248+ // FIXME: Broken false positives, currently unhandled
249+ // my_bad_macro!("{}", local_i32);
250+ // my_bad_macro2!("{}", local_i32);
251+ // used_twice! {
252+ // large = "large value: {}",
253+ // small = "small value: {}",
254+ // local_i32,
255+ // };
256+ }
257+
258+ // Add new tests right above this line to keep existing test line numbers intact.
259+ // The main function is the only one that be kept at the end.
260+ fn main() {
261+ tester(42);
262+ tester2();
263+ }
0 commit comments