Skip to content

Commit 7e06561

Browse files
AmateurECEojeda
authored andcommitted
rust: macros: enable paste! use from macro_rules!
According to the rustdoc for the proc_macro crate[1], tokens captured from a "macro variable" (e.g. from within macro_rules!) may be delimited by invisible tokens and be contained within a proc_macro::Group. Previously, this scenario was not handled by macros::paste, which caused a proc-macro panic when the corresponding tests are enabled. Enable the tests, and handle this case by making macros::paste::concat recursive. Link: https://doc.rust-lang.org/stable/proc_macro/enum.Delimiter.html [1] Signed-off-by: Ethan D. Twardy <[email protected]> Reviewed-by: Alice Ryhl <[email protected]> Link: #1076 Link: https://lore.kernel.org/r/[email protected] [ Rebased (one fix was already applied) and reworded. Remove unneeded `rust` as language in examples. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 8d3f507 commit 7e06561

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

rust/macros/lib.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,12 +304,25 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
304304
///
305305
/// # Example
306306
///
307-
/// ```ignore
308-
/// use kernel::macro::paste;
309-
///
307+
/// ```
308+
/// # const binder_driver_return_protocol_BR_OK: u32 = 0;
309+
/// # const binder_driver_return_protocol_BR_ERROR: u32 = 1;
310+
/// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2;
311+
/// # const binder_driver_return_protocol_BR_REPLY: u32 = 3;
312+
/// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4;
313+
/// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5;
314+
/// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6;
315+
/// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7;
316+
/// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8;
317+
/// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9;
318+
/// # const binder_driver_return_protocol_BR_NOOP: u32 = 10;
319+
/// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11;
320+
/// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12;
321+
/// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13;
322+
/// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14;
310323
/// macro_rules! pub_no_prefix {
311324
/// ($prefix:ident, $($newname:ident),+) => {
312-
/// paste! {
325+
/// kernel::macros::paste! {
313326
/// $(pub(crate) const $newname: u32 = [<$prefix $newname>];)+
314327
/// }
315328
/// };
@@ -348,9 +361,22 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
348361
/// * `lower`: change the identifier to lower case.
349362
/// * `upper`: change the identifier to upper case.
350363
///
351-
/// ```ignore
352-
/// use kernel::macro::paste;
353-
///
364+
/// ```
365+
/// # const binder_driver_return_protocol_BR_OK: u32 = 0;
366+
/// # const binder_driver_return_protocol_BR_ERROR: u32 = 1;
367+
/// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2;
368+
/// # const binder_driver_return_protocol_BR_REPLY: u32 = 3;
369+
/// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4;
370+
/// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5;
371+
/// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6;
372+
/// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7;
373+
/// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8;
374+
/// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9;
375+
/// # const binder_driver_return_protocol_BR_NOOP: u32 = 10;
376+
/// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11;
377+
/// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12;
378+
/// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13;
379+
/// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14;
354380
/// macro_rules! pub_no_prefix {
355381
/// ($prefix:ident, $($newname:ident),+) => {
356382
/// kernel::macros::paste! {
@@ -385,7 +411,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
385411
///
386412
/// Literals can also be concatenated with other identifiers:
387413
///
388-
/// ```ignore
414+
/// ```
389415
/// macro_rules! create_numbered_fn {
390416
/// ($name:literal, $val:literal) => {
391417
/// kernel::macros::paste! {

rust/macros/paste.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use proc_macro::{Delimiter, Group, Ident, Spacing, Span, TokenTree};
44

5-
fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
5+
fn concat_helper(tokens: &[TokenTree]) -> Vec<(String, Span)> {
66
let mut tokens = tokens.iter();
77
let mut segments = Vec::new();
88
let mut span = None;
@@ -46,12 +46,21 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
4646
};
4747
segments.push((value, sp));
4848
}
49-
_ => panic!("unexpected token in paste segments"),
49+
Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::None => {
50+
let tokens = group.stream().into_iter().collect::<Vec<TokenTree>>();
51+
segments.append(&mut concat_helper(tokens.as_slice()));
52+
}
53+
token => panic!("unexpected token in paste segments: {:?}", token),
5054
};
5155
}
5256

57+
segments
58+
}
59+
60+
fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
61+
let segments = concat_helper(tokens);
5362
let pasted: String = segments.into_iter().map(|x| x.0).collect();
54-
TokenTree::Ident(Ident::new(&pasted, span.unwrap_or(group_span)))
63+
TokenTree::Ident(Ident::new(&pasted, group_span))
5564
}
5665

5766
pub(crate) fn expand(tokens: &mut Vec<TokenTree>) {

0 commit comments

Comments
 (0)