|
| 1 | +# `macro_metavar_expr_concat` |
| 2 | + |
| 3 | +The tracking issue for this feature is: [#124225] |
| 4 | + |
| 5 | +------------------------ |
| 6 | + |
| 7 | +In stable Rust, there is no way to create new identifiers by joining identifiers to literals or other identifiers without using procedural macros such as [`paste`]. |
| 8 | + `#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression. |
| 9 | + |
| 10 | +> This feature uses the syntax from [`macro_metavar_expr`] but is otherwise |
| 11 | +> independent. It replaces the old unstable feature [`concat_idents`]. |
| 12 | +
|
| 13 | +> This is an experimental feature; it and its syntax will require a RFC before stabilization. |
| 14 | +
|
| 15 | + |
| 16 | +### Overview |
| 17 | + |
| 18 | +`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable expression for creating new identifiers: |
| 19 | + |
| 20 | +```rust |
| 21 | +#![feature(macro_metavar_expr_concat)] |
| 22 | + |
| 23 | +macro_rules! create_some_structs { |
| 24 | + ($name:ident) => { |
| 25 | + pub struct ${ concat(First, $name) }; |
| 26 | + pub struct ${ concat(Second, $name) }; |
| 27 | + pub struct ${ concat(Third, $name) }; |
| 28 | + } |
| 29 | +} |
| 30 | + |
| 31 | +create_some_structs!(Thing); |
| 32 | +``` |
| 33 | + |
| 34 | +This macro invocation expands to: |
| 35 | + |
| 36 | +```rust |
| 37 | +pub struct FirstThing; |
| 38 | +pub struct SecondThing; |
| 39 | +pub struct ThirdThing; |
| 40 | +``` |
| 41 | + |
| 42 | +### Syntax |
| 43 | + |
| 44 | +This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]). |
| 45 | + `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or literals. |
| 46 | + |
| 47 | +### Examples |
| 48 | + |
| 49 | +#### Create a function or method with a concatenated name |
| 50 | + |
| 51 | +```rust |
| 52 | +#![feature(macro_metavar_expr_concat)] |
| 53 | + |
| 54 | +macro_rules! make_getter { |
| 55 | + ($name:ident, $field: ident, $ret:ty) => { |
| 56 | + impl $name { |
| 57 | + pub fn ${ concat(get_, $field) }(&self) -> &$ret { |
| 58 | + &self.$field |
| 59 | + } |
| 60 | + } |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +pub struct Thing { |
| 65 | + description: String, |
| 66 | +} |
| 67 | + |
| 68 | +make_getter!(Thing, description, String); |
| 69 | +``` |
| 70 | + |
| 71 | +This expands to: |
| 72 | + |
| 73 | +```rust |
| 74 | +pub struct Thing { |
| 75 | + description: String, |
| 76 | +} |
| 77 | + |
| 78 | +impl Thing { |
| 79 | + pub fn get_description(&self) -> &String { |
| 80 | + &self.description |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +#### Create names for macro generated tests |
| 86 | + |
| 87 | +```rust |
| 88 | +#![feature(macro_metavar_expr_concat)] |
| 89 | + |
| 90 | +macro_rules! test_math { |
| 91 | + ($integer:ident) => { |
| 92 | + #[test] |
| 93 | + fn ${ concat(test_, $integer, _, addition) } () { |
| 94 | + let a: $integer = 73; |
| 95 | + let b: $integer = 42; |
| 96 | + assert_eq!(a + b, 115) |
| 97 | + } |
| 98 | + |
| 99 | + #[test] |
| 100 | + fn ${ concat(test_, $integer, _, subtraction) } () { |
| 101 | + let a: $integer = 73; |
| 102 | + let b: $integer = 42; |
| 103 | + assert_eq!(a - b, 31) |
| 104 | + } |
| 105 | + } |
| 106 | +} |
| 107 | + |
| 108 | +test_math!(i32); |
| 109 | +test_math!(u64); |
| 110 | +test_math!(u128); |
| 111 | +``` |
| 112 | + |
| 113 | +Running this returns the following output: |
| 114 | + |
| 115 | +```text |
| 116 | +running 6 tests |
| 117 | +test test_i32_subtraction ... ok |
| 118 | +test test_i32_addition ... ok |
| 119 | +test test_u128_addition ... ok |
| 120 | +test test_u128_subtraction ... ok |
| 121 | +test test_u64_addition ... ok |
| 122 | +test test_u64_subtraction ... ok |
| 123 | +
|
| 124 | +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s |
| 125 | +``` |
| 126 | + |
| 127 | +[`paste`]: https://crates.io/crates/paste |
| 128 | +[RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html |
| 129 | +[`concat_idents!`]: https://doc.rust-lang.org/nightly/std/macro.concat_idents.html |
| 130 | +[`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md |
| 131 | +[`concat_idents`]: ../library-features/concat-idents.md |
| 132 | +[#124225]: https://github.com/rust-lang/rust/issues/124225 |
| 133 | +[declarative macros]: https://doc.rust-lang.org/stable/reference/macros-by-example.html |
0 commit comments