-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Macro matching is incorrect for macros invoked in macro expansions #26361
Comments
isn't this a feature too? I have macros where I don't want to risk that a user-supplied parameter matches such a “literal” parameter that you have in ‘bool’ etc in your example. |
I think the current behaviour makes sense - once you've matched |
@rust-lang/lang , is this a bug or not? |
cc @jseyfried |
Personally, I consider this a bug, but it may not be a bug we want to fix in the existing macros because of backwards compat. I've never liked how macros insert "pseudo-tokens" representing parsed entities -- although I understand the original motivation, which was to avoid the performance cost of re-parsing things over and over. I just think it should be an optimization, and not something that has visible effects on the behavior of the code. (But all that said, it can't be as simple as "paste the tokens $foo where it appears". For example, if you have |
Initial implementation of declarative macros 2.0 Implement declarative macros 2.0 (rust-lang/rfcs#1584) behind `#![feature(decl_macro)]`. Differences from `macro_rules!` include: - new syntax: `macro m(..) { .. }` instead of `macro_rules! m { (..) => { .. } }` - declarative macros are items: ```rust // crate A: mod foo { m!(); // use before definition; declaration order is irrelevant pub macro m() {} // `pub`, `pub(super)`, etc. work } fn main() { foo::m!(); // named like other items { use foo::m as n; n!(); } // imported like other items } pub use foo::m; // re-exported like other items // crate B: extern crate A; // no need for `#[macro_use]` A::foo::m!(); A::m!(); ``` - Racket-like hygiene for items, imports, methods, fields, type parameters, privacy, etc. - Intuitively, names in a macro definition are resolved in the macro definition's scope, not the scope in which the macro is used. - This [explaination](http://beautifulracket.com/explainer/hygiene.html) of hygiene for Racket applies here (except for the "Breaking Hygiene" section). I wrote a similar [explanation](https://github.com/jseyfried/rfcs/blob/hygiene/text/0000-hygiene.md) for Rust. - Generally speaking, if `fn f() { <body> }` resolves, `pub macro m() { <body> } ... m!()` also resolves, even if `m!()` is in a separate crate. - `::foo::bar` in a `macro` behaves like `$crate::foo::bar` in a `macro_rules!`, except it can access everything visible from the `macro` (thus more permissive). - See [`src/test/{run-pass, compile-fail}/hygiene`](afe7d89) for examples. Small example: ```rust mod foo { fn f() { println!("hello world"); } pub macro m() { f(); } } fn main() { foo::m!(); } ``` Limitations: - This does not address planned changes to matchers (`expr`,`ty`, etc.), c.f. #26361. - Lints (including stability and deprecation) and `unsafe` are not hygienic. - adding hygiene here will be mostly or entirely backwards compatible - Nested macro definitions (a `macro` inside another `macro`) don't always work correctly when invoked from external crates. - pending improvements in how we encode macro definitions in crate metadata - There is no way to "escape" hygiene without using a procedural macro. r? @nrc
Initial implementation of declarative macros 2.0 Implement declarative macros 2.0 (rust-lang/rfcs#1584) behind `#![feature(decl_macro)]`. Differences from `macro_rules!` include: - new syntax: `macro m(..) { .. }` instead of `macro_rules! m { (..) => { .. } }` - declarative macros are items: ```rust // crate A: pub mod foo { m!(); // use before definition; declaration order is irrelevant pub macro m() {} // `pub`, `pub(super)`, etc. work } fn main() { foo::m!(); // named like other items { use foo::m as n; n!(); } // imported like other items } pub use foo::m; // re-exported like other items // crate B: extern crate A; // no need for `#[macro_use]` A::foo::m!(); A::m!(); ``` - Racket-like hygiene for items, imports, methods, fields, type parameters, privacy, etc. - Intuitively, names in a macro definition are resolved in the macro definition's scope, not the scope in which the macro is used. - This [explaination](http://beautifulracket.com/explainer/hygiene.html) of hygiene for Racket applies here (except for the "Breaking Hygiene" section). I wrote a similar [explanation](https://github.com/jseyfried/rfcs/blob/hygiene/text/0000-hygiene.md) for Rust. - Generally speaking, if `fn f() { <body> }` resolves, `pub macro m() { <body> } ... m!()` also resolves, even if `m!()` is in a separate crate. - `::foo::bar` in a `macro` behaves like `$crate::foo::bar` in a `macro_rules!`, except it can access everything visible from the `macro` (thus more permissive). - See [`src/test/{run-pass, compile-fail}/hygiene`](afe7d89) for examples. Small example: ```rust mod foo { fn f() { println!("hello world"); } pub macro m() { f(); } } fn main() { foo::m!(); } ``` Limitations: - This does not address planned changes to matchers (`expr`,`ty`, etc.), c.f. #26361. - Lints (including stability and deprecation) and `unsafe` are not hygienic. - adding hygiene here will be mostly or entirely backwards compatible - Nested macro definitions (a `macro` inside another `macro`) don't always work correctly when invoked from external crates. - pending improvements in how we encode macro definitions in crate metadata - There is no way to "escape" hygiene without using a procedural macro. r? @nrc
Triage: not any changes here. Per niko's last comment, I am guessing this is a WONTFIX, especially given that nobody else other than the original reporter has commented here, really. I'm gonna give this one a close for now, please let me know if this is still useful to track. |
Example: http://is.gd/y5Wa67
This example should print "Type::Byte" but instead prints "Type::Struct". Calling
ty_to_type!
directly onu8
works, as does havingforwards!
receive att
rather than aty
.The text was updated successfully, but these errors were encountered: