Comments (13)
Regarding syntax, I would prefer a space-separated form like ${concat(get_ $item _mut)}
, rather than the current comma-separated ${concat(get_, $item, _mut)}
. That just makes it easier to read imo, and matches paste
.
from rust.
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.
from rust.
Sorry if this is the wrong place to discuss this, but should ${concat}
provide its own case-conversion mechanism (just like paste!
does), or should we instead provide a standalone ${case}
metavar expr to handle this?
If we where to follow paste!
syntax, then it would look like:
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 ${case}
metavar expr:
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 paste!
simplicity. The advantage of ${case}
over ${concat}
would be that, currently, ${concat}
requires 2 operands to be able to be used (this could technically be changed), so ${case}
would allow:
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.
from rust.
The introduction of
${case}
as a new metavariable expression that can be used with or without${concat}
looks worth pursuing and semantically correct but IFAICT, inputs currently only accept ad-hoc parameters. More specifically,${concat}
only accepts literal identifiers and variables.// 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?
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 ${concat($a, concat($b, $c)}
would be able to be made non ambiguous; I would imagine this kind of analysis would be hard to pull off, since you can't no longer look for ${}
to know that the next thing is a metavar expr identifier.
$ident:modifier
Looks 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 = (); } }
Do note that if $ident:modifier
is accepted as the final syntax, it would only work inside of ${concat}
or ${case}
, which would remove the ambiguity for let $a:upper = ();
; identifiers can't use the :
symbol, so let ${case($a:upper)} = ();
is non ambiguous.
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 ${$ident:modifier}
(without writing case
), but I don't know if case-conversion is important enough to have its own syntax (I also don't know what other modifiers you could really add to these).
These are just my opinions. A theoretical stabilization of
${concat}
with or without case modifiers is fine to me.
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. :)
from rust.
This still needs a T-lang shepherd, right?
from rust.
This still needs a T-lang shepherd, right?
Unfortunately I am not familiar or aware of this procedure.
from rust.
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 concat_idents
(the latter has stalled, blocked on design concerns, see its tracking issue).
Please consult the tracking issue description for more context.
from rust.
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.
from rust.
Thank you @joshtriplett
from rust.
Well, I personally don't mind discussing potential designs in a tracking issue.
${case}
The introduction of ${case}
as a new metavariable expression that can be used with or without ${concat}
looks worth pursuing and semantically correct but IFAICT, inputs currently only accept ad-hoc parameters. More specifically, ${concat}
only accepts literal identifiers and variables.
// 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:modifier
Looks 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 ${concat}
with or without case modifiers is fine to me.
from rust.
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 paste
version works without errors.
I can go a bit further with ignore
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.
from rust.
Looks like a bug to me. I will try to investigate it in the following weeks
from rust.
It would be nice if there was some way to allow turning ${concat(c, $litstr)}
into c"some string"
for constructing C string literals when a Rust string is provided. That is, a replacement for cstr!
. But I can't think of a good syntax here.
#127542 adds support for literals, but the above would get turned into (invalid) identifier csome string
.
from rust.
Related Issues (20)
- bootstrap: `core::config::tests::detect_src_and_out` test fails if checkout is not under `C` drive HOT 1
- compiler_fence documentation is misleading HOT 1
- 1.80.1 requires additional type annotations, thus failing to compile previously working code HOT 2
- ICE: unexpected non-type Node::GenericParam HOT 3
- LLVM debuginfo assertion "overlapping or duplicate fragments" fails with ridiculous MIR inlining
- ICE: `None` in compiler/rustc_middle/src/ty/sty.rs HOT 2
- Specific inline ASM in specific project generates invalid ASM HOT 3
- multiple platforms incorrectly impl `thread::sleep` with `Duration::as_micros` HOT 4
- ICE: `Encountered error SignatureMismatch`
- ICE: no `enclosing_body_owner` for hir_id HOT 1
- ICE: `associated type missing default`
- ICE: invalid pointer unsizing &dyn Foo -> [i32]
- using extern "x86-interrupt" + #[naked] + kernel address sanitizer crashes compiler HOT 4
- Compiler panics when i run cargo check HOT 3
- const_heap feature can be used to leak mutable memory into final value of constant
- `-Zthreads` is slower the more cores I add HOT 1
- `std::fs::canonicalize` failed to process path mounted with cppcryptfs/dokan under windows HOT 2
- rustc_driver: There is no explanation of when the IRs (HIR, THIR, MIR) become available.
- Delay def creation for expression-like nodes HOT 1
- Refining generic bounds in trait method HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust.