diff options
author | Björn Roy Baron <bjorn3_gh@protonmail.com> | 2022-11-10 17:41:17 +0100 |
---|---|---|
committer | Miguel Ojeda <ojeda@kernel.org> | 2022-12-04 01:59:04 +0100 |
commit | 60f18c225f5f6939e348c4b067711d10afd33151 (patch) | |
tree | 7f60e3ef1510b5f5645a19f6197655921d8b4127 /rust/macros/concat_idents.rs | |
parent | c3630df66f95e6c18987734b39f0239303dd72d8 (diff) | |
download | linux-60f18c225f5f6939e348c4b067711d10afd33151.tar.gz linux-60f18c225f5f6939e348c4b067711d10afd33151.tar.bz2 linux-60f18c225f5f6939e348c4b067711d10afd33151.zip |
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>
Diffstat (limited to 'rust/macros/concat_idents.rs')
-rw-r--r-- | rust/macros/concat_idents.rs | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/rust/macros/concat_idents.rs b/rust/macros/concat_idents.rs new file mode 100644 index 000000000000..7e4b450f3a50 --- /dev/null +++ b/rust/macros/concat_idents.rs @@ -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)]) +} |