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
Add a new concat metavar expr #118958
base: master
Are you sure you want to change the base?
Add a new concat metavar expr #118958
Conversation
(rustbot has picked a reviewer for you, use r? to override) |
5e8fac5
to
b08d90b
Compare
This comment has been minimized.
This comment has been minimized.
97b22d8
to
c04e3a6
Compare
@rustbot label +A-macros |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good to me. I started some discussion in wg-macros https://rust-lang.zulipchat.com/#narrow/stream/404510-wg-macros/topic/concat_idents.20as.20metavar.20.24.7B.2E.2E.2E.7D.
I don't think you need to mention the RFC in the title/commit message since this specific function wasn't called out in the RFC.
"concat" => { | ||
let lhs_is_var = try_eat_dollar(&mut iter); | ||
let lhs_ident = parse_ident(&mut iter, sess, ident.span)?; | ||
if !try_eat_comma(&mut iter) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we even need commas? Referencing paste
again, the syntax is
[<Q R S T>] // turns into QRST
Which is somewhat easier to read without the commas. (Similar to C Q ## R ## S ## T
, though that definitely isn't easier to read)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comma was added to follow the syntax of the other meta-variable expressions. For example: count($foo, 0)
.
In my personal opinion, the matter about case conversion and omission of commas should be discussed at a later opportunity.
c04e3a6
to
7695bdf
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
aed2b0e
to
5242d59
Compare
(please use |
@c410-f3r is this ready for review? I didn't intend for my comments to be blocking |
Yeap, it is ready for review @rustbot labels -S-waiting-on-author +S-waiting-on-review |
This comment was marked as resolved.
This comment was marked as resolved.
error: expected identifier, found `$` | ||
--> $DIR/syntax-errors.rs:178:15 | ||
| | ||
LL | const ${concat($sign name, _123)}: () = (); | ||
| ^ expected identifier | ||
... | ||
LL | tt_that_is_dollar_sign_with_concat!($, FOO); | ||
| ------------------------------------------- in this macro invocation | ||
| | ||
= note: this error originates in the macro `tt_that_is_dollar_sign_with_concat` (in Nightly builds, run with -Z macro-backtrace for more info) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to point to a better span? this looks like the problem is that const ${concat(...)}
is not supported at all, but the actual problem seems to be $sign
?..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This diagnostic isn't originated from parse_ident
. Mabe something after expansion?
If a better span is desirable, then a separated investigation should be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parse_ident
shouldn't take a span from the outside in general.
It should use span of the unexpected token in its errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IFAICT, this specific diagnostic wasn't emitted by parse_ident
.
But regardless parse_ident
was modified to use as much span from tokens as possible. The outside span is still being used in case the RefTokenTreeCursor
iterator doesn't yield.
result.push(TokenTree::Token( | ||
Token::from_ast_ident(Ident::new(Symbol::intern(&concatenated), visited_span())), | ||
Spacing::Alone, | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the tests I still don't quite get how hygiene works...tests/ui/macros/rfc-3086-metavar-expr/concat-hygiene.rs
implies that xy
and ${concat($x, $y)}
are different, but then tests/ui/macros/rfc-3086-metavar-expr/concat.rs
uses things defined inside the macro outside of it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marker
is the responsible entity that process hygiene for tokens emitted by meta-variable expressions.
Its internal aspects are not entirely clear to me but if you want to know how everything works I guess @petrochenkov can give you a better answer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation marks the result as coming from the macro (using span of the metavar expression itself), regardless of contexts of the concatenated identifiers.
concat_idents!()
macro works in a similar way, ignoring input contexts, but the output context is assigned in a different way.
What the desired behavior should be is a design question.
- Are we supposed to use local variables produced by concat inside
macro_rules
(macros 1.0) outside of the macro? Not sure. - Are we supposed to use any names produced by concat inside
macro
(macros 2.0) outside of the macro?
Likely yes, so some kind of hygiene opt out, or support for inheriting context from some token, should be added, but that applies to many things produced bymacro
, not justconcat
.
5242d59
to
ecbb5d6
Compare
It might not be a bad idea to put this under a separate feature gate from the rest of |
r? compiler |
r? @tgross35 may I let you review this? |
@Nadrieril I don't know enough about this area to make a call (also don't have r+), but this looks fine to me with a feature gate added. If this isn't your area either then I guess we can see who gets the hot potato next. r? compiler |
Reroll since Wesley passed off the review initially r? compiler |
I suspect r? @petrochenkov might be more suitable? |
|
||
macro_rules! tt_that_is_dollar_sign_with_concat { | ||
($sign:tt, $name:ident) => { | ||
const ${concat($sign name, _123)}: () = (); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not specific to concat
, right?
Macros don't generally treat $dollar name
as $name
in any contexts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this test is therefore unnecessary. Removed.
error: expected identifier, found `$` | ||
--> $DIR/syntax-errors.rs:178:15 | ||
| | ||
LL | const ${concat($sign name, _123)}: () = (); | ||
| ^ expected identifier | ||
... | ||
LL | tt_that_is_dollar_sign_with_concat!($, FOO); | ||
| ------------------------------------------- in this macro invocation | ||
| | ||
= note: this error originates in the macro `tt_that_is_dollar_sign_with_concat` (in Nightly builds, run with -Z macro-backtrace for more info) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parse_ident
shouldn't take a span from the outside in general.
It should use span of the unexpected token in its errors.
let mut result = Vec::new(); | ||
result.push(element(&mut iter, sess, ident.span)?); | ||
if !try_eat_comma(&mut iter) { | ||
return Err(sess.dcx.struct_span_err(ident.span, "expected comma")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this should use span of the unexpected token.
result.push(TokenTree::Token( | ||
Token::from_ast_ident(Ident::new(Symbol::intern(&concatenated), visited_span())), | ||
Spacing::Alone, | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation marks the result as coming from the macro (using span of the metavar expression itself), regardless of contexts of the concatenated identifiers.
concat_idents!()
macro works in a similar way, ignoring input contexts, but the output context is assigned in a different way.
What the desired behavior should be is a design question.
- Are we supposed to use local variables produced by concat inside
macro_rules
(macros 1.0) outside of the macro? Not sure. - Are we supposed to use any names produced by concat inside
macro
(macros 2.0) outside of the macro?
Likely yes, so some kind of hygiene opt out, or support for inheriting context from some token, should be added, but that applies to many things produced bymacro
, not justconcat
.
e810b88
to
2ce0a7b
Compare
This comment has been minimized.
This comment has been minimized.
Thanks for the review. Let me know if anything is missing. Questions around potential design concerns were placed in the requested tracking issue. |
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
.In other words, forgetting the dollar symbol can produce undesired outputs.
cc #29599