Skip to content

Commit 85525ed

Browse files
Darksonnojeda
authored andcommittedMar 9, 2025
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>
1 parent 901b329 commit 85525ed

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed
 

‎rust/macros/quote.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ impl ToTokens for proc_macro::Group {
2020
}
2121
}
2222

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+
2329
impl ToTokens for TokenTree {
2430
fn to_tokens(&self, tokens: &mut TokenStream) {
2531
tokens.extend([self.clone()]);
@@ -40,7 +46,7 @@ impl ToTokens for TokenStream {
4046
/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
4147
macro_rules! quote_spanned {
4248
($span:expr => $($tt:tt)*) => {{
43-
let mut tokens;
49+
let mut tokens: ::std::vec::Vec<::proc_macro::TokenTree>;
4450
#[allow(clippy::vec_init_then_push)]
4551
{
4652
tokens = ::std::vec::Vec::new();
@@ -65,7 +71,8 @@ macro_rules! quote_spanned {
6571
quote_spanned!(@proc $v $span $($tt)*);
6672
};
6773
(@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
68-
let mut tokens = ::std::vec::Vec::new();
74+
#[allow(unused_mut)]
75+
let mut tokens = ::std::vec::Vec::<::proc_macro::TokenTree>::new();
6976
quote_spanned!(@proc tokens $span $($inner)*);
7077
$v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
7178
::proc_macro::Delimiter::Parenthesis,
@@ -136,6 +143,22 @@ macro_rules! quote_spanned {
136143
));
137144
quote_spanned!(@proc $v $span $($tt)*);
138145
};
146+
(@proc $v:ident $span:ident = $($tt:tt)*) => {
147+
$v.push(::proc_macro::TokenTree::Punct(
148+
::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone)
149+
));
150+
quote_spanned!(@proc $v $span $($tt)*);
151+
};
152+
(@proc $v:ident $span:ident # $($tt:tt)*) => {
153+
$v.push(::proc_macro::TokenTree::Punct(
154+
::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone)
155+
));
156+
quote_spanned!(@proc $v $span $($tt)*);
157+
};
158+
(@proc $v:ident $span:ident _ $($tt:tt)*) => {
159+
$v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new("_", $span)));
160+
quote_spanned!(@proc $v $span $($tt)*);
161+
};
139162
(@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
140163
$v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(stringify!($id), $span)));
141164
quote_spanned!(@proc $v $span $($tt)*);

0 commit comments

Comments
 (0)
Please sign in to comment.