mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
rust: macros: add concat_idents!
proc macro
This macro provides similar functionality to the unstable feature `concat_idents` without having to rely on it. For instance: let x_1 = 42; let x_2 = concat_idents!(x, _1); assert!(x_1 == x_2); It has different behavior with respect to macro hygiene. Unlike the unstable `concat_idents!` macro, it allows, for example, referring to local variables by taking the span of the second macro as span for the output identifier. Signed-off-by: Björn Roy Baron <bjorn3_gh@protonmail.com> Reviewed-by: Finn Behrens <me@kloenk.dev> Reviewed-by: Gary Guo <gary@garyguo.net> [Reworded, adapted for upstream and applied latest changes] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
c3630df66f
commit
60f18c225f
23
rust/macros/concat_idents.rs
Normal file
23
rust/macros/concat_idents.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro::{token_stream, Ident, TokenStream, TokenTree};
|
||||
|
||||
use crate::helpers::expect_punct;
|
||||
|
||||
fn expect_ident(it: &mut token_stream::IntoIter) -> Ident {
|
||||
if let Some(TokenTree::Ident(ident)) = it.next() {
|
||||
ident
|
||||
} else {
|
||||
panic!("Expected Ident")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn concat_idents(ts: TokenStream) -> TokenStream {
|
||||
let mut it = ts.into_iter();
|
||||
let a = expect_ident(&mut it);
|
||||
assert_eq!(expect_punct(&mut it), ',');
|
||||
let b = expect_ident(&mut it);
|
||||
assert!(it.next().is_none(), "only two idents can be concatenated");
|
||||
let res = Ident::new(&format!("{a}{b}"), b.span());
|
||||
TokenStream::from_iter([TokenTree::Ident(res)])
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
//! Crate for all kernel procedural macros.
|
||||
|
||||
mod concat_idents;
|
||||
mod helpers;
|
||||
mod module;
|
||||
|
||||
@ -70,3 +71,46 @@ use proc_macro::TokenStream;
|
||||
pub fn module(ts: TokenStream) -> TokenStream {
|
||||
module::module(ts)
|
||||
}
|
||||
|
||||
/// Concatenate two identifiers.
|
||||
///
|
||||
/// This is useful in macros that need to declare or reference items with names
|
||||
/// starting with a fixed prefix and ending in a user specified name. The resulting
|
||||
/// identifier has the span of the second argument.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use kernel::macro::concat_idents;
|
||||
///
|
||||
/// macro_rules! pub_no_prefix {
|
||||
/// ($prefix:ident, $($newname:ident),+) => {
|
||||
/// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+
|
||||
/// };
|
||||
/// }
|
||||
///
|
||||
/// pub_no_prefix!(
|
||||
/// binder_driver_return_protocol_,
|
||||
/// BR_OK,
|
||||
/// BR_ERROR,
|
||||
/// BR_TRANSACTION,
|
||||
/// BR_REPLY,
|
||||
/// BR_DEAD_REPLY,
|
||||
/// BR_TRANSACTION_COMPLETE,
|
||||
/// BR_INCREFS,
|
||||
/// BR_ACQUIRE,
|
||||
/// BR_RELEASE,
|
||||
/// BR_DECREFS,
|
||||
/// BR_NOOP,
|
||||
/// BR_SPAWN_LOOPER,
|
||||
/// BR_DEAD_BINDER,
|
||||
/// BR_CLEAR_DEATH_NOTIFICATION_DONE,
|
||||
/// BR_FAILED_REPLY
|
||||
/// );
|
||||
///
|
||||
/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn concat_idents(ts: TokenStream) -> TokenStream {
|
||||
concat_idents::concat_idents(ts)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user