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 <tmgross@umich.edu> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> Reviewed-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20231118013959.37384-1-tmgross@umich.edu [ Added `:` before example block. ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
743766565d
commit
2dc318ea96
@ -254,8 +254,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
|
||||
/// single identifier.
|
||||
///
|
||||
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers
|
||||
/// (literals, lifetimes and documentation strings are not supported). There is a difference in
|
||||
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
|
||||
/// literals (lifetimes and documentation strings are not supported). There is a difference in
|
||||
/// supported modifiers as well.
|
||||
///
|
||||
/// # Example
|
||||
@ -337,6 +337,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
|
||||
/// ```
|
||||
///
|
||||
/// # Literals
|
||||
///
|
||||
/// Literals can also be concatenated with other identifiers:
|
||||
///
|
||||
/// ```ignore
|
||||
/// macro_rules! create_numbered_fn {
|
||||
/// ($name:literal, $val:literal) => {
|
||||
/// kernel::macros::paste! {
|
||||
/// fn [<some_ $name _fn $val>]() -> u32 { $val }
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
///
|
||||
/// create_numbered_fn!("foo", 100);
|
||||
///
|
||||
/// assert_eq!(some_foo_fn100(), 100)
|
||||
/// ```
|
||||
///
|
||||
/// [`paste`]: https://docs.rs/paste/
|
||||
#[proc_macro]
|
||||
pub fn paste(input: TokenStream) -> TokenStream {
|
||||
|
@ -9,7 +9,15 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
|
||||
loop {
|
||||
match tokens.next() {
|
||||
None => break,
|
||||
Some(TokenTree::Literal(lit)) => segments.push((lit.to_string(), lit.span())),
|
||||
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#") {
|
||||
|
Loading…
Reference in New Issue
Block a user