Skip to content

Commit 85f8a26

Browse files
committed
Add expression interpolation with #{expr}
One annoyance I frequently run into with the `quote!` macro is that I need to lift out all variable bindings that are being interpolated. For example I'll often do: let name = &foo.name; let abi = &foo.abi; quote! { extern #abi fn #name() { /* ... */ } } but I've recently had the idea that in addition to lighteight `#name` interpolation there's also available syntax (I believe) to support expression interpolation as well, implemented in this PR. The above snippet could now be rewritten as: quote! { extern #{foo.abi} fn #{foo.name} { /* ... */ } }
1 parent 44038ca commit 85f8a26

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ pub mod __rt {
254254
/// [`ToTokens`]: trait.ToTokens.html
255255
/// [Syn]: https://github.com/dtolnay/syn
256256
///
257+
/// You can also use `#{expr}` to interpolate an arbitrary expression, so long
258+
/// as the result implements the [`ToTokens`] trait. For example `#{1 + 3}` will
259+
/// interpolate `4i32`.
260+
///
257261
/// Repetition is done using `#(...)*` or `#(...),*` again similar to
258262
/// `macro_rules!`. This iterates through the elements of any variable
259263
/// interpolated within the repetition and inserts a copy of the repetition body
@@ -579,6 +583,11 @@ macro_rules! quote_each_token {
579583
quote_each_token!($tokens $span $($rest)*);
580584
};
581585

586+
($tokens:ident $span:ident # { $val:expr } $($rest:tt)*) => {
587+
$crate::ToTokens::to_tokens(&$val, &mut $tokens);
588+
quote_each_token!($tokens $span $($rest)*);
589+
};
590+
582591
($tokens:ident $span:ident # $first:ident $($rest:tt)*) => {
583592
$crate::ToTokens::to_tokens(&$first, &mut $tokens);
584593
quote_each_token!($tokens $span $($rest)*);

tests/test.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,19 @@ fn test_append_tokens() {
293293
a.append_all(b);
294294
assert_eq!("a b", a.to_string());
295295
}
296+
297+
#[test]
298+
fn whole_exprs() {
299+
let x = X;
300+
let tokens = quote!(#{x});
301+
assert_eq!(tokens.to_string(), "X");
302+
303+
let tokens = quote!(#{1 + 2});
304+
assert_eq!(tokens.to_string(), "3i32");
305+
306+
struct A { b: X }
307+
let x = A { b: X };
308+
309+
let tokens = quote!(#{x.b});
310+
assert_eq!(tokens.to_string(), "X");
311+
}

0 commit comments

Comments
 (0)