Skip to content

Commit 2dc318e

Browse files
tgross35ojeda
authored andcommitted
rust: macros: update 'paste!' macro to accept string literals
Enable combining identifiers with literals in the 'paste!' macro. This allows combining user-specified strings with affixes to create namespaced identifiers. This sample code: macro_rules! m { ($name:lit) => { paste!(struct [<_some_ $name _struct_>] {}) } } m!("foo_bar"); Would previously cause a compilation error. It will now generate: struct _some_foo_bar_struct_ {} Signed-off-by: Trevor Gross <[email protected]> Reviewed-by: Martin Rodriguez Reboredo <[email protected]> Reviewed-by: Vincenzo Palazzo <[email protected]> Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Benno Lossin <[email protected]> Reviewed-by: Gary Guo <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Added `:` before example block. ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 7437665 commit 2dc318e

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

rust/macros/lib.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
254254
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
255255
/// single identifier.
256256
///
257-
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers
258-
/// (literals, lifetimes and documentation strings are not supported). There is a difference in
257+
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
258+
/// literals (lifetimes and documentation strings are not supported). There is a difference in
259259
/// supported modifiers as well.
260260
///
261261
/// # Example
@@ -337,6 +337,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
337337
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
338338
/// ```
339339
///
340+
/// # Literals
341+
///
342+
/// Literals can also be concatenated with other identifiers:
343+
///
344+
/// ```ignore
345+
/// macro_rules! create_numbered_fn {
346+
/// ($name:literal, $val:literal) => {
347+
/// kernel::macros::paste! {
348+
/// fn [<some_ $name _fn $val>]() -> u32 { $val }
349+
/// }
350+
/// };
351+
/// }
352+
///
353+
/// create_numbered_fn!("foo", 100);
354+
///
355+
/// assert_eq!(some_foo_fn100(), 100)
356+
/// ```
357+
///
340358
/// [`paste`]: https://docs.rs/paste/
341359
#[proc_macro]
342360
pub fn paste(input: TokenStream) -> TokenStream {

rust/macros/paste.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
99
loop {
1010
match tokens.next() {
1111
None => break,
12-
Some(TokenTree::Literal(lit)) => segments.push((lit.to_string(), lit.span())),
12+
Some(TokenTree::Literal(lit)) => {
13+
// Allow us to concat string literals by stripping quotes
14+
let mut value = lit.to_string();
15+
if value.starts_with('"') && value.ends_with('"') {
16+
value.remove(0);
17+
value.pop();
18+
}
19+
segments.push((value, lit.span()));
20+
}
1321
Some(TokenTree::Ident(ident)) => {
1422
let mut value = ident.to_string();
1523
if value.starts_with("r#") {

0 commit comments

Comments
 (0)