-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Support nested macro_rules!
#34925
Support nested macro_rules!
#34925
Conversation
@@ -2663,7 +2665,7 @@ impl<'a> Parser<'a> { | |||
} | |||
|
|||
pub fn check_unknown_macro_variable(&mut self) { | |||
if self.quote_depth == 0 { | |||
if self.quote_depth == 0 && !self.parsing_token_tree { |
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.
I believe quote_depth
and parsing_token_tree
have the exact same intended function.
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.
I tried just using quote_depth
and it caused other problems.
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.
Specifically, it caused problems with parsing the left hand side of a macro_rules!
body. I didn't look into it in too much detail since I wanted to do this PR as simply as possible.
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.
Could we remove quote_depth
then?
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.
I don't think so -- looking into it some more, the problem is that this condition needs to be false when parsing the lhs of a macro_rules!
body.
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.
It's always false
because quote_depth
is never anything other than 0
.
EDIT: Oops, the modifications to quote_depth
are in another module.
IMO, the whole distinction between $ ident
(two tokens) and $ident
(one token) is unnecessary and only creates complications.
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.
Agreed (out of the scope of this PR, though).
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.
Removed quote_depth
and parsing_token_tree
in #39419.
cc @nrc |
@bors r+ |
📌 Commit 485e2df has been approved by |
⌛ Testing commit 485e2df with merge c3f1268... |
💔 Test failed - auto-win-gnu-32-opt-rustbuild |
@bors: retry On Tue, Jul 19, 2016 at 9:40 PM, bors [email protected] wrote:
|
⌛ Testing commit 485e2df with merge f83586d... |
💔 Test failed - auto-linux-64-cargotest |
@bors: retry On Wed, Jul 20, 2016 at 5:58 PM, bors [email protected] wrote:
|
⌛ Testing commit 485e2df with merge d62bb9d... |
💔 Test failed - auto-win-gnu-32-opt |
@bors: retry sorry for the number of retries... On Thu, Jul 21, 2016 at 12:37 PM, bors [email protected] wrote:
|
⌛ Testing commit 485e2df with merge 8445fd4... |
💔 Test failed - auto-win-gnu-32-opt |
@bors: retry On Fri, Jul 22, 2016 at 4:13 PM, bors [email protected] wrote:
|
Amazing. This is kinda funny though... macro_rules! outer {
($b:tt $c:ident) => {
macro_rules! inner {
($a $b $c) => { }
}
}
}
outer!(: ident); // NB: must be `:`
inner!(foo); |
This has added a deadlock: macro_rules! outer {
($b:tt) => {
macro_rules! inner {
($b) => { }
}
}
}
outer!($a); // OK
outer!($b); // hangs the compiler |
@durka Thanks, I'll look into |
It's not a compiler NOTE, I meant if you don't pass |
@durka I think that has to do with how we parse |
It can't be in all cases, since I passed in the |
I fixed the deadlock in #35453. |
macros: Make metavariables hygienic This PR makes metavariables hygienic. For example, consider: ```rust macro_rules! foo { ($x:tt) => { // Suppose that this token tree argument is always a metavariable. macro_rules! bar { ($x:expr, $y:expr) => { ($x, $y) } } } } fn main() { foo!($z); // This currently compiles. foo!($y); // This is an error today but compiles after this PR. } ``` Today, the `macro_rules! bar { ... }` definition is only valid when the metavariable passed to `foo` is not `$y` (since it unhygienically conflicts with the `$y` in the definition of `bar`) or `$x` (c.f. #35450). After this PR, the definition of `bar` is always valid (and `bar!(a, b)` always expands to `(a, b)` as expected). This can break code that was allowed in #34925 (landed two weeks ago). For example, ```rust macro_rules! outer { ($t:tt) => { macro_rules! inner { ($i:item) => { $t } } } } outer!($i); // This `$i` should not interact with the `$i` in the definition of `inner!`. inner!(fn main() {}); // After this PR, this is an error ("unknown macro variable `i`"). ``` Due to the severe limitations on nested `macro_rules!` before #34925, this is not a breaking change for stable/beta. Fixes #35450. r? @nrc
Fixes #6994.
r? @eddyb