Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: macros: support additional tokens in quote!

This gives the quote! macro support for the following additional tokens:

* The = token.
* The _ token.
* The # token. (when not followed by an identifier)
* Using #my_var with variables of type Ident.

Additionally, some type annotations are added to allow cases where
groups are empty. For example, quote! does support () in the input, but
only when it is *not* empty. When it is empty, there are zero `.push`
calls, so the compiler can't infer the item type and also emits a
warning about it not needing to be mutable.

These additional quote! features are used by a new proc macro that
generates code looking like this:

const _: () = {
if true {
::kernel::bindings::#name
} else {
#name
};
};

where #name has type Ident.

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250303-export-macro-v3-2-41fbad85a27f@google.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Alice Ryhl and committed by
Miguel Ojeda
85525eda 901b3290

+25 -2
+25 -2
rust/macros/quote.rs
··· 20 20 } 21 21 } 22 22 23 + impl ToTokens for proc_macro::Ident { 24 + fn to_tokens(&self, tokens: &mut TokenStream) { 25 + tokens.extend([TokenTree::from(self.clone())]); 26 + } 27 + } 28 + 23 29 impl ToTokens for TokenTree { 24 30 fn to_tokens(&self, tokens: &mut TokenStream) { 25 31 tokens.extend([self.clone()]); ··· 46 40 /// `quote` crate but provides only just enough functionality needed by the current `macros` crate. 47 41 macro_rules! quote_spanned { 48 42 ($span:expr => $($tt:tt)*) => {{ 49 - let mut tokens; 43 + let mut tokens: ::std::vec::Vec<::proc_macro::TokenTree>; 50 44 #[allow(clippy::vec_init_then_push)] 51 45 { 52 46 tokens = ::std::vec::Vec::new(); ··· 71 65 quote_spanned!(@proc $v $span $($tt)*); 72 66 }; 73 67 (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => { 74 - let mut tokens = ::std::vec::Vec::new(); 68 + #[allow(unused_mut)] 69 + let mut tokens = ::std::vec::Vec::<::proc_macro::TokenTree>::new(); 75 70 quote_spanned!(@proc tokens $span $($inner)*); 76 71 $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( 77 72 ::proc_macro::Delimiter::Parenthesis, ··· 141 134 $v.push(::proc_macro::TokenTree::Punct( 142 135 ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone) 143 136 )); 137 + quote_spanned!(@proc $v $span $($tt)*); 138 + }; 139 + (@proc $v:ident $span:ident = $($tt:tt)*) => { 140 + $v.push(::proc_macro::TokenTree::Punct( 141 + ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone) 142 + )); 143 + quote_spanned!(@proc $v $span $($tt)*); 144 + }; 145 + (@proc $v:ident $span:ident # $($tt:tt)*) => { 146 + $v.push(::proc_macro::TokenTree::Punct( 147 + ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone) 148 + )); 149 + quote_spanned!(@proc $v $span $($tt)*); 150 + }; 151 + (@proc $v:ident $span:ident _ $($tt:tt)*) => { 152 + $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new("_", $span))); 144 153 quote_spanned!(@proc $v $span $($tt)*); 145 154 }; 146 155 (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {