mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	 211dcf7785
			
		
	
	
		211dcf7785
		
	
	
	
	
		
			
			Starting with Rust 1.88.0 (expected 2025-06-26) [1], `rustc` may move
back the `uninlined_format_args` to `style` from `pedantic` (it was
there waiting for rust-analyzer suppotr), and thus we will start to see
lints like:
    warning: variables can be used directly in the `format!` string
       --> rust/macros/kunit.rs:105:37
        |
    105 |         let kunit_wrapper_fn_name = format!("kunit_rust_wrapper_{}", test);
        |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
    help: change this to
        |
    105 -         let kunit_wrapper_fn_name = format!("kunit_rust_wrapper_{}", test);
    105 +         let kunit_wrapper_fn_name = format!("kunit_rust_wrapper_{test}");
There is even a case that is a pure removal:
    warning: variables can be used directly in the `format!` string
      --> rust/macros/module.rs:51:13
       |
    51 |             format!("{field}={content}\0", field = field, content = content)
       |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
    help: change this to
       |
    51 -             format!("{field}={content}\0", field = field, content = content)
    51 +             format!("{field}={content}\0")
The lints all seem like nice cleanups, thus just apply them.
We may want to disable `allow-mixed-uninlined-format-args` in the future.
Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Link: https://github.com/rust-lang/rust-clippy/pull/14160 [1]
Acked-by: Benno Lossin <lossin@kernel.org>
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250502140237.1659624-6-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
		
	
			
		
			
				
	
	
		
			113 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| 
 | |
| use proc_macro::{Delimiter, Group, Ident, Spacing, Span, TokenTree};
 | |
| 
 | |
| fn concat_helper(tokens: &[TokenTree]) -> Vec<(String, Span)> {
 | |
|     let mut tokens = tokens.iter();
 | |
|     let mut segments = Vec::new();
 | |
|     let mut span = None;
 | |
|     loop {
 | |
|         match tokens.next() {
 | |
|             None => break,
 | |
|             Some(TokenTree::Literal(lit)) => {
 | |
|                 // Allow us to concat string literals by stripping quotes
 | |
|                 let mut value = lit.to_string();
 | |
|                 if value.starts_with('"') && value.ends_with('"') {
 | |
|                     value.remove(0);
 | |
|                     value.pop();
 | |
|                 }
 | |
|                 segments.push((value, lit.span()));
 | |
|             }
 | |
|             Some(TokenTree::Ident(ident)) => {
 | |
|                 let mut value = ident.to_string();
 | |
|                 if value.starts_with("r#") {
 | |
|                     value.replace_range(0..2, "");
 | |
|                 }
 | |
|                 segments.push((value, ident.span()));
 | |
|             }
 | |
|             Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
 | |
|                 let Some(TokenTree::Ident(ident)) = tokens.next() else {
 | |
|                     panic!("expected identifier as modifier");
 | |
|                 };
 | |
| 
 | |
|                 let (mut value, sp) = segments.pop().expect("expected identifier before modifier");
 | |
|                 match ident.to_string().as_str() {
 | |
|                     // Set the overall span of concatenated token as current span
 | |
|                     "span" => {
 | |
|                         assert!(
 | |
|                             span.is_none(),
 | |
|                             "span modifier should only appear at most once"
 | |
|                         );
 | |
|                         span = Some(sp);
 | |
|                     }
 | |
|                     "lower" => value = value.to_lowercase(),
 | |
|                     "upper" => value = value.to_uppercase(),
 | |
|                     v => panic!("unknown modifier `{v}`"),
 | |
|                 };
 | |
|                 segments.push((value, sp));
 | |
|             }
 | |
|             Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::None => {
 | |
|                 let tokens = group.stream().into_iter().collect::<Vec<TokenTree>>();
 | |
|                 segments.append(&mut concat_helper(tokens.as_slice()));
 | |
|             }
 | |
|             token => panic!("unexpected token in paste segments: {token:?}"),
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     segments
 | |
| }
 | |
| 
 | |
| fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
 | |
|     let segments = concat_helper(tokens);
 | |
|     let pasted: String = segments.into_iter().map(|x| x.0).collect();
 | |
|     TokenTree::Ident(Ident::new(&pasted, group_span))
 | |
| }
 | |
| 
 | |
| pub(crate) fn expand(tokens: &mut Vec<TokenTree>) {
 | |
|     for token in tokens.iter_mut() {
 | |
|         if let TokenTree::Group(group) = token {
 | |
|             let delimiter = group.delimiter();
 | |
|             let span = group.span();
 | |
|             let mut stream: Vec<_> = group.stream().into_iter().collect();
 | |
|             // Find groups that looks like `[< A B C D >]`
 | |
|             if delimiter == Delimiter::Bracket
 | |
|                 && stream.len() >= 3
 | |
|                 && matches!(&stream[0], TokenTree::Punct(p) if p.as_char() == '<')
 | |
|                 && matches!(&stream[stream.len() - 1], TokenTree::Punct(p) if p.as_char() == '>')
 | |
|             {
 | |
|                 // Replace the group with concatenated token
 | |
|                 *token = concat(&stream[1..stream.len() - 1], span);
 | |
|             } else {
 | |
|                 // Recursively expand tokens inside the group
 | |
|                 expand(&mut stream);
 | |
|                 let mut group = Group::new(delimiter, stream.into_iter().collect());
 | |
|                 group.set_span(span);
 | |
|                 *token = TokenTree::Group(group);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Path segments cannot contain invisible delimiter group, so remove them if any.
 | |
|     for i in (0..tokens.len().saturating_sub(3)).rev() {
 | |
|         // Looking for a double colon
 | |
|         if matches!(
 | |
|             (&tokens[i + 1], &tokens[i + 2]),
 | |
|             (TokenTree::Punct(a), TokenTree::Punct(b))
 | |
|                 if a.as_char() == ':' && a.spacing() == Spacing::Joint && b.as_char() == ':'
 | |
|         ) {
 | |
|             match &tokens[i + 3] {
 | |
|                 TokenTree::Group(group) if group.delimiter() == Delimiter::None => {
 | |
|                     tokens.splice(i + 3..i + 4, group.stream());
 | |
|                 }
 | |
|                 _ => (),
 | |
|             }
 | |
| 
 | |
|             match &tokens[i] {
 | |
|                 TokenTree::Group(group) if group.delimiter() == Delimiter::None => {
 | |
|                     tokens.splice(i..i + 1, group.stream());
 | |
|                 }
 | |
|                 _ => (),
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |