-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking Issue for macro_metavar_expr_concat
#124225
Comments
This still needs a T-lang shepherd, right? |
Unfortunately I am not familiar or aware of this procedure. |
All language features have to go through the RFC process eventually. However, the implementation can be done before an RFC has been written by following T-lang's experimental feature process which requires a T-lang member to support — shepherd — the venture. Only “small” language (not compiler) “fixes” don't need to follow the RFC process, they just need a T-lang FCP. |
T-lang, this feature is seeking a shepherd, therefore I'm nominating this for you. An implementation is already under way (#118958). This feature adds a new kind of macro metavariable expression (the latter (overarching) feature has been approved by the merged RFC 3086, see also its tracking issue and stabilization PR (proposed FCP, disposition: merge)). The feature represents a more potent alternative / potential successor to the unstable built-in macro Please consult the tracking issue description for more context. |
Happy to second this with my T-lang hat on. @c410-f3r Good luck, and please reach out to #t-lang on Zulip if you have any questions. Feel free to @ me there if needed. |
Thank you @joshtriplett |
Add a new concat metavar expr Revival of rust-lang#111930 Giving it another try now that rust-lang#117050 was merged. With the new rules, meta-variable expressions must be referenced with a dollar sign (`$`) and this can cause misunderstands with `$concat`. ```rust macro_rules! foo { ( $bar:ident ) => { const ${concat(VAR, bar)}: i32 = 1; }; } // Will produce `VARbar` instead of `VAR_123` foo!(_123); ``` In other words, forgetting the dollar symbol can produce undesired outputs. cc rust-lang#29599 cc rust-lang#124225
Sorry if this is the wrong place to discuss this, but should If we where to follow macro_rules! many_idents {
($a:ident, $c:ident) => {
const ${concat($a:upper, B, $c:lower, D)}: i32 = 1;
};
}
fn main() {
many_idents!(a, C);
assert_eq!(ABcD, 1);
} Or with a future macro_rules! many_idents {
($a:ident, $c:ident) => {
const ${concat(${case($a, upper)}, B, ${case($c, lower)}, D)}: i32 = 1;
};
}
fn main() {
many_idents!(a, C);
assert_eq!(ABcD, 1);
} Which I think is way too verbose, but maybe I'm just too used to use std::ops::Add;
pub struct Wrapper<T>(T);
macro_rules! impl_op {
($Op:ident => $Ty:ty) => {
impl $Op<$Ty> for Wrapper<$Ty> {
type Output = Self;
// alternative syntax; `:` instead of `,`.
fn ${case($Op:snake)}(self, rhs: $Ty) -> Self::Output {
Self(self.0.${case($Op:snake)}(rhs))
}
}
};
}
impl_op!(Add => u8); With that said, maybe there is a world where both approaches are accepted, but I think there is probably less motivation to do that? cc @c410-f3r @joshtriplett for opinions about this. |
Well, I personally don't mind discussing potential designs in a tracking issue. ${case}The introduction of // Same problem with multiples `${concat}`s
macro_rules! foo {
($a:ident, $b:ident, $c:ident) => {
let ${concat(a, ${concat(b, c)})}: () = (); // ERROR !
}
} Perhaps the evaluation of nested metaravariables expressions will become a thing someday? $ident:modifierLooks feasible in regards to a possible implementation but semantically awkward IMO. I am not aware of something similar in the macro system. If acceptable, then it should probably be restricted to a subset of operations. macro_rules! foo {
($a:ident) => {
// Is it OK?
let $a:upper = ();
}
} These are just my opinions. A theoretical stabilization of |
Oh I wasn't aware of that limitation. I imagine that something like that would be needed down the line. I don't much about the internals of the macro codebase, so I wouldn't know if this would be hard to implement. As a side note, I wonder if something like
Do note that if With that said, you made me realize that with this change some metavar exprs would have "special syntax" attached to them, which might not be the desired design, specially because most users would think about metavar exprs as functions rather than "fancier macros" (although accepting this change would contradict this). Another option would be to allow a standalone syntax
This is something that can go under "Future possibilities" on the final RFC. I don't particularly think that stabilization should be blocked on this, since we can always add it later. :) |
Add a new concat metavar expr Revival of #111930 Giving it another try now that #117050 was merged. With the new rules, meta-variable expressions must be referenced with a dollar sign (`$`) and this can cause misunderstands with `$concat`. ```rust macro_rules! foo { ( $bar:ident ) => { const ${concat(VAR, bar)}: i32 = 1; }; } // Will produce `VARbar` instead of `VAR_123` foo!(_123); ``` In other words, forgetting the dollar symbol can produce undesired outputs. cc #29599 cc rust-lang/rust#124225
Add a new concat metavar expr Revival of #111930 Giving it another try now that #117050 was merged. With the new rules, meta-variable expressions must be referenced with a dollar sign (`$`) and this can cause misunderstands with `$concat`. ```rust macro_rules! foo { ( $bar:ident ) => { const ${concat(VAR, bar)}: i32 = 1; }; } // Will produce `VARbar` instead of `VAR_123` foo!(_123); ``` In other words, forgetting the dollar symbol can produce undesired outputs. cc #29599 cc rust-lang/rust#124225
Is it a known issue that this doesn't seem to work with identifiers repeating at a depth? #![feature(macro_metavar_expr_concat)]
macro_rules! many_idents {
($a:ident, $c:ident) => {
const ${concat($a, B, $c, D)}: i32 = 1;
};
}
// Paste implementation included for reference
macro_rules! many_idents_paste {
($a:ident, $c:ident) => {
paste::paste! {
const [<$a B $c D>]: i32 = 2;
}
};
}
macro_rules! many_idents_multi_metavar {
($($a:ident, $c:ident;)*) => {
$(
const ${concat($a, B, $c, D)}: i32 = 3;
)*
};
}
// Paste implementation included for reference
macro_rules! many_idents_multi_paste {
($($a:ident, $c:ident;)*) => {
$(
paste::paste! {
const [<$a B $c D>]: i32 = 3;
}
)*
};
}
fn main() {
many_idents!(A, C);
assert_eq!(ABCD, 1);
many_idents_paste!(F, G);
assert_eq!(FBGD, 2);
many_idents_multi_paste! {
H, I;
J, K;
L, M;
}
assert_eq!(HBID, 3);
assert_eq!(JBKD, 3);
assert_eq!(LBMD, 3);
many_idents_multi_metavar! {
N, O;
P, Q;
R, S;
}
} error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
--> src/main.rs:19:10
|
19 | $(
| __________^
20 | | const ${concat($a, B, $c, D)}: i32 = 3;
21 | | )*
| |_________^ The I can go a bit further with macro_rules! many_idents_multi_metavar {
($($a:ident, $c:ident;)*) => {
$(
${ignore($a)}
${ignore($c)}
const ${concat($a, B, $c, D)}: i32 = 3;
)*
};
} But then I get: error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
--> src/main.rs:22:29
|
22 | const ${concat($a, B, $c, D)}: i32 = 3;
| This seems like a major limitation. |
Looks like a bug to me. I will try to investigate it in the following weeks |
Add a new concat metavar expr Revival of #111930 Giving it another try now that #117050 was merged. With the new rules, meta-variable expressions must be referenced with a dollar sign (`$`) and this can cause misunderstands with `$concat`. ```rust macro_rules! foo { ( $bar:ident ) => { const ${concat(VAR, bar)}: i32 = 1; }; } // Will produce `VARbar` instead of `VAR_123` foo!(_123); ``` In other words, forgetting the dollar symbol can produce undesired outputs. cc #29599 cc rust-lang/rust#124225
[`macro_metavar_expr_concat`] Add support for literals Adds support for things like `${concat($variable, 123)}` or `${concat("hello", "_world")}` . cc rust-lang#124225
[`macro_metavar_expr_concat`] Add support for literals Adds support for things like `${concat($variable, 123)}` or `${concat("hello", "_world")}` . cc rust-lang#124225
Rollup merge of rust-lang#126841 - c410-f3r:concat-again, r=petrochenkov [`macro_metavar_expr_concat`] Add support for literals Adds support for things like `${concat($variable, 123)}` or `${concat("hello", "_world")}` . cc rust-lang#124225
[`macro_metavar_expr_concat`] Add support for literals Adds support for literals in macro parameters. ```rust macro_rules! with_literal { ($literal:literal) => { const ${concat(FOO, $literal)}: i32 = 1; } } fn main() { with_literal!("_BAR"); assert_eq!(FOO_BAR, 1); } ``` cc rust-lang#124225 r? `@petrochenkov`
[`macro_metavar_expr_concat`] Add support for literals Adds support for literals in macro parameters. ```rust macro_rules! with_literal { ($literal:literal) => { const ${concat(FOO, $literal)}: i32 = 1; } } fn main() { with_literal!("_BAR"); assert_eq!(FOO_BAR, 1); } ``` cc rust-lang#124225 r? ``@petrochenkov``
It would be nice if there was some way to allow turning #127542 adds support for literals, but the above would get turned into (invalid) identifier |
Regarding syntax, I would prefer a space-separated form like |
Rollup merge of rust-lang#127542 - c410-f3r:concat-again, r=petrochenkov [`macro_metavar_expr_concat`] Add support for literals Adds support for literals in macro parameters. ```rust macro_rules! with_literal { ($literal:literal) => { const ${concat(FOO, $literal)}: i32 = 1; } } fn main() { with_literal!("_BAR"); assert_eq!(FOO_BAR, 1); } ``` cc rust-lang#124225 r? ``@petrochenkov``
…gjubilee [`macro_metavar_expr_concat`] Dogfooding cc rust-lang#124225 Starts inner usage to test the robustness of the implementation.
Rollup merge of rust-lang#128491 - c410-f3r:unlock-rfc-2011, r=workingjubilee [`macro_metavar_expr_concat`] Dogfooding cc rust-lang#124225 Starts inner usage to test the robustness of the implementation.
🚀 I found a way to evaluate And in other words, Also, Also, https://crates.io/crates/with_builtin_macros allows one to use // (This code was not tested, may contain typos)
fn concat_idents!(a, b) () {} // Doesn't work
with_builtin_macros::with_eager_expansions! {
fn #{ concat_idents!(a, b) } () {} // Works! Even on stable!
}
macro_rules! this_macro_accepts_ident {
($a:ident) => {}
}
// Doesn't work, because "this_macro_accepts_ident" evaluates before "concat_idents"
this_macro_accepts_ident!(concat_idents!(a, b));
with_builtin_macros::with_eager_expansions! {
this_macro_accepts_ident!(#{ concat_idents!(a, b) }); // Works! Even on stable!
}
macro_rules! this_macro_accepts_literal {
($a:literal) => {}
}
// Doesn't work.
// Moreover, you cannot solve this problem using #[feature(macro_metavar_expr_concat)],
// because ${concat(...)} produces identifier, not string literal!!!
// Same applies to "paste"! "paste::paste!" deals with identifiers, not strings. So, with_builtin_macros is the only way!!!
this_macro_accepts_literal!(concat!("a", "b"));
with_builtin_macros::with_eager_expansions! {
this_macro_accepts_literal!(#{ concat!("a", "b") }); // Works! Even on stable!
} |
This is a tracking issue for the experimental feature macro metavariable expression
concat
(RFC pending).The feature gate for the issue is
#![feature(macro_metavar_expr_concat)]
.Provides a modern alternative to the
concat_idents!
macro.About experimental features
An experimental feature is one that has not yet had an RFC. The idea is to allow implementation work to proceed to better inform an upcoming RFC. Experimental features cannot be stabilized without first having an RFC. The existence of an experimental feature does not indicate lang team consensus that the feature is desirable, only that there is a problem that is worthy of being solved and that the idea has enough merit to consider exploring. See the lang team process page for more details.
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps / History
Unresolved Questions
r#foo
raw identifiers? Add a new concat metavar expr #118958 (comment)References
The text was updated successfully, but these errors were encountered: