From e21e9734780080026c39c22200272d97ebd9f63a Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 5 Apr 2025 20:40:53 +0200 Subject: [PATCH 1/3] unstable book; document `macro_metavar_expr_concat` --- .../macro-metavar-expr-concat.md | 154 ++++++++++++++++++ .../language-features/macro-metavar-expr.md | 10 ++ .../src/library-features/concat-idents.md | 2 + 3 files changed, 166 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md create mode 100644 src/doc/unstable-book/src/language-features/macro-metavar-expr.md diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md new file mode 100644 index 00000000000..663cb442d6c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md @@ -0,0 +1,154 @@ +# `macro_metavar_expr_concat` + +The tracking issue for this feature is: [#124225] + +------------------------ + + +`#![feature(macro_metavar_expr_concat)]` provides a more powerful alternative to [`concat_idents!`]. + +> This feature is not to be confused with [`macro_metavar_expr`] or [`concat_idents`]. + +> This is an experimental feature; it and its syntax will require a RFC before stabilization. + + +### Overview + +`macro_rules!` macros cannot create new identifiers and use them in ident positions. +A common use case is the need to create new structs or functions. The following cannot be done[^1]: + +```rust,compile_fail +macro_rules! create_some_structs { + ($name:ident) => { + // Invalid syntax + struct First_$name; + // Also invalid syntax + struct Second_($name); + // Macros are not allowed in this position + // (This restriction is what makes `concat_idents!` useless) + struct concat_idents!(Third_, $name); + } +} +# create_some_structs!(Thing); +``` + +`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable to concatenate idents in ident position: + +```rust +#![feature(macro_metavar_expr_concat)] +# #![allow(non_camel_case_types, dead_code)] + +macro_rules! create_some_structs { + ($name:ident) => { + struct ${ concat(First_, $name) }; + struct ${ concat(Second_, $name) }; + struct ${ concat(Third_, $name) }; + } +} + +create_some_structs!(Thing); +``` + +This macro invocation expands to: + +```rust +# #![allow(non_camel_case_types, dead_code)] +struct First_Thing; +struct Second_Thing; +struct Third_Thing; +``` + +### Syntax + +This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]). + `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or string literals. + +### Examples + +#### Create a function or method with a concatenated name + +```rust +#![feature(macro_metavar_expr_concat)] +# #![allow(non_camel_case_types, dead_code)] + +macro_rules! make_getter { + ($name:ident, $field: ident, $ret:ty) => { + impl $name { + pub fn ${ concat(get_, $field) }(&self) -> &$ret { + &self.$field + } + } + } +} + +pub struct Thing { + description: String, +} + +make_getter!(Thing, description, String); +``` + +This expands to: + +```rust +pub struct Thing { + description: String, +} + +impl Thing { + pub fn get_description(&self) -> &String { + &self.description + } +} +``` + +#### Create names for macro generated tests + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! test_math { + ($integer:ident) => { + #[test] + fn ${ concat(test_, $integer, _, addition) } () { + let a: $integer = 73; + let b: $integer = 42; + assert_eq!(a + b, 115) + } + + #[test] + fn ${ concat(test_, $integer, _, subtraction) } () { + let a: $integer = 73; + let b: $integer = 42; + assert_eq!(a - b, 31) + } + } +} + +test_math!(i32); +test_math!(u64); +test_math!(u128); +``` + +Running this returns the following output: + +```text +running 6 tests +test test_i32_subtraction ... ok +test test_i32_addition ... ok +test test_u128_addition ... ok +test test_u128_subtraction ... ok +test test_u64_addition ... ok +test test_u64_subtraction ... ok + +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +[^1]: An alternative is the [`paste`] crate. + +[`paste`]: https://crates.io/crates/paste +[RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html +[`concat_idents!`]: https://doc.rust-lang.org/nightly/std/macro.concat_idents.html +[`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md +[`concat_idents`]: ../library-features/concat-idents.md +[#124225]: https://github.com/rust-lang/rust/issues/124225 diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr.md new file mode 100644 index 00000000000..7ce64c1a354 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr.md @@ -0,0 +1,10 @@ +# `macro_metavar_expr` + +The tracking issue for this feature is: [#83527] + +------------------------ + +> This feature is not to be confused with [`macro_metavar_expr_concat`]. + +[`macro_metavar_expr_concat`]: ./macro-metavar-expr-concat.md +[#83527]: https://github.com/rust-lang/rust/issues/83527 diff --git a/src/doc/unstable-book/src/library-features/concat-idents.md b/src/doc/unstable-book/src/library-features/concat-idents.md index 73f6cfa2178..76dffc289a0 100644 --- a/src/doc/unstable-book/src/library-features/concat-idents.md +++ b/src/doc/unstable-book/src/library-features/concat-idents.md @@ -6,6 +6,8 @@ The tracking issue for this feature is: [#29599] ------------------------ +> This feature is expected to be removed in favor of [`macro_metavar_expr_concat`](../language-features/macro-metavar-expr-concat.md). + The `concat_idents` feature adds a macro for concatenating multiple identifiers into one identifier. From 16ad7b9286025afd20416635de9cf4ef26953c04 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 8 Apr 2025 15:15:32 +0200 Subject: [PATCH 2/3] Formatting and apply feedback --- .../macro-metavar-expr-concat.md | 62 +++++++++---------- .../src/library-features/concat-idents.md | 2 +- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md index 663cb442d6c..41613313cd3 100644 --- a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md +++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md @@ -4,8 +4,8 @@ The tracking issue for this feature is: [#124225] ------------------------ - -`#![feature(macro_metavar_expr_concat)]` provides a more powerful alternative to [`concat_idents!`]. +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`]. + `#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression. > This feature is not to be confused with [`macro_metavar_expr`] or [`concat_idents`]. @@ -14,36 +14,35 @@ The tracking issue for this feature is: [#124225] ### Overview -`macro_rules!` macros cannot create new identifiers and use them in ident positions. -A common use case is the need to create new structs or functions. The following cannot be done[^1]: +At this time, [declarative macros] cannot create new identifiers. +A common use case is the need to create names for structs or functions. The following cannot be done on stable Rust[^1]: ```rust,compile_fail macro_rules! create_some_structs { - ($name:ident) => { - // Invalid syntax - struct First_$name; - // Also invalid syntax - struct Second_($name); - // Macros are not allowed in this position - // (This restriction is what makes `concat_idents!` useless) - struct concat_idents!(Third_, $name); - } + ($name:ident) => { + // Invalid syntax + pub struct First$name; + // Also invalid syntax + pub struct Second($name); + // Macros are not allowed in this position + // (This restriction is what makes `concat_idents!` useless) + pub struct concat_idents!(Third, $name); + } } # create_some_structs!(Thing); ``` -`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable to concatenate idents in ident position: +`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable to concatenate idents: ```rust #![feature(macro_metavar_expr_concat)] -# #![allow(non_camel_case_types, dead_code)] macro_rules! create_some_structs { - ($name:ident) => { - struct ${ concat(First_, $name) }; - struct ${ concat(Second_, $name) }; - struct ${ concat(Third_, $name) }; - } + ($name:ident) => { + pub struct ${ concat(First, $name) }; + pub struct ${ concat(Second, $name) }; + pub struct ${ concat(Third, $name) }; + } } create_some_structs!(Thing); @@ -52,10 +51,9 @@ create_some_structs!(Thing); This macro invocation expands to: ```rust -# #![allow(non_camel_case_types, dead_code)] -struct First_Thing; -struct Second_Thing; -struct Third_Thing; +pub struct FirstThing; +pub struct SecondThing; +pub struct ThirdThing; ``` ### Syntax @@ -69,16 +67,15 @@ This feature builds upon the metavariable expression syntax `${ .. }` as specifi ```rust #![feature(macro_metavar_expr_concat)] -# #![allow(non_camel_case_types, dead_code)] macro_rules! make_getter { - ($name:ident, $field: ident, $ret:ty) => { - impl $name { - pub fn ${ concat(get_, $field) }(&self) -> &$ret { - &self.$field - } - } - } + ($name:ident, $field: ident, $ret:ty) => { + impl $name { + pub fn ${ concat(get_, $field) }(&self) -> &$ret { + &self.$field + } + } + } } pub struct Thing { @@ -152,3 +149,4 @@ test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; fini [`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md [`concat_idents`]: ../library-features/concat-idents.md [#124225]: https://github.com/rust-lang/rust/issues/124225 +[declarative macros]: https://doc.rust-lang.org/stable/reference/macros-by-example.html diff --git a/src/doc/unstable-book/src/library-features/concat-idents.md b/src/doc/unstable-book/src/library-features/concat-idents.md index 76dffc289a0..4366172fb99 100644 --- a/src/doc/unstable-book/src/library-features/concat-idents.md +++ b/src/doc/unstable-book/src/library-features/concat-idents.md @@ -6,7 +6,7 @@ The tracking issue for this feature is: [#29599] ------------------------ -> This feature is expected to be removed in favor of [`macro_metavar_expr_concat`](../language-features/macro-metavar-expr-concat.md). +> This feature is expected to be superseded by [`macro_metavar_expr_concat`](../language-features/macro-metavar-expr-concat.md). The `concat_idents` feature adds a macro for concatenating multiple identifiers into one identifier. From 17242309a709bea79cbb6a2244fef360281f1539 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Wed, 9 Apr 2025 22:10:16 +0200 Subject: [PATCH 3/3] Apply more feedback --- .../macro-metavar-expr-concat.md | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md index 41613313cd3..b6dbdb14407 100644 --- a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md +++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md @@ -7,32 +7,15 @@ The tracking issue for this feature is: [#124225] 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`]. `#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression. -> This feature is not to be confused with [`macro_metavar_expr`] or [`concat_idents`]. +> This feature uses the syntax from [`macro_metavar_expr`] but is otherwise +> independent. It replaces the old unstable feature [`concat_idents`]. > This is an experimental feature; it and its syntax will require a RFC before stabilization. ### Overview -At this time, [declarative macros] cannot create new identifiers. -A common use case is the need to create names for structs or functions. The following cannot be done on stable Rust[^1]: - -```rust,compile_fail -macro_rules! create_some_structs { - ($name:ident) => { - // Invalid syntax - pub struct First$name; - // Also invalid syntax - pub struct Second($name); - // Macros are not allowed in this position - // (This restriction is what makes `concat_idents!` useless) - pub struct concat_idents!(Third, $name); - } -} -# create_some_structs!(Thing); -``` - -`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable to concatenate idents: +`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable expression for creating new identifiers: ```rust #![feature(macro_metavar_expr_concat)] @@ -59,7 +42,7 @@ pub struct ThirdThing; ### Syntax This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]). - `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or string literals. + `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or literals. ### Examples @@ -141,8 +124,6 @@ test test_u64_subtraction ... ok test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` -[^1]: An alternative is the [`paste`] crate. - [`paste`]: https://crates.io/crates/paste [RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html [`concat_idents!`]: https://doc.rust-lang.org/nightly/std/macro.concat_idents.html