-
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
Macro hygiene for patterns breaks due to static/const in scope #22462
Comments
(Also, even if I am wrong and we somehow do respect hygiene with respect to static identifiers, the pretty-printer probably needs a mode where it includes hygiene information to ensure identifiers are unique in the generated code, when the goal is to be able to recompile the output in the manner expected by our |
We don't have hygiene for items at all. There's no way to resolve item definitions at the macro definition site, therefore something as simple as macro_rules! foo {
() => (None);
} is un-hygienically capturing an item from the invocation's environment. This might be tolerable if it could not interfere with local bindings, but your example demonstrates this is not the case. The problem here is that Rust uses capitalization for this distinction, but only by convention, not as part of the language. Perhaps there is a minimally-invasive way to enshrine the convention, just within the pattern grammar, where it seems most needed. More thoughts on this soon. |
We could do this with two new pattern forms,
(keywords / tokens tbb), where an unadorned ident is "inferred" based on the Unicode character class of the first character. I'd like to think and discuss a bit more before drafting an RFC. |
Here is an example that does not involve macro_rules! foo {
($e:expr) => {
match $e {
x => println!("{}", x),
}
}
}
fn main() {
const x: u32 = 2;
foo!(3);
}
|
I think that's a bug in our test suite. The compiler plugin docs explicitly point out that the |
Personally I don't think the lack of general item name hygiene warrants a substantial change to the pattern grammar, especially this late in the game. You can also envision programs like the following: fn foo() {}
macro_rules! invoke_foo(
() => (foo())
);
fn main() {
fn foo() { panic!(":("); }
invoke_foo!();
} and so I think the lack of hygiene for items is going to be problematic in other ways anyway. As a user I don't necessarily mind your example not working as much as I think the diagnostic could be improved. I think even in the general case when you intend to use a binding as a catch-all pattern but it gets resolved to an item, we could be more precise and have
be followed with a help note
|
I agree, and fixing it is high on my list of priorities for macro rules two point oh. It'll be a big task, though. I think interfering with local |
Although it doesn't work today, I think we could accept On the other hand I don't think let x @ _ = ... is an acceptable solution. I should reiterate that my preferred solution is a syntax change which makes all patterns locally unambiguous — probably by inferring from case, with explicit fallbacks like |
(closing as wont-fix; we cannot fix this backwards compatibly, and do not think it realistic to try to change this aspect of |
@pnkfelix: I think the fix where |
@kmcallister I suspect I would support such an RFC, since it was with very heavy heart that I even closed this in the first place |
@kmcallister oh and the |
(reopening mostly to remind myself to look into why |
I was just getting compiler errors before, but amazingly it gets worse: #22850 I think these are just bugs, though. We just need to be consistent about whether |
I think situations where enum Foo { Bar }
const baz: Foo = Foo::Bar;
let baz = Foo::Bar; produces
even though, technically, the pattern is irrefutable. This is good for us because it means that unconditionally parsing that as a binding occurrence of |
Not going to have time to work on this for 1.0-final, sorry. |
I still want to try to look into this; assigning to self. |
I also observed
I find it strange, because I can't say I wanted to refer to that global static |
nota bene: The |
Today, this gives a different error:
I'm not sure if this ticket is still valid or not; I'm not sure that we're planning on making major changes to macro_rules, so this might be WONTFIX? |
I think the error we give is at least very clear so I'm going to close. It's unlikely we're going to make the changes that are asked for here for macro_rules specifically. |
Given that we now have editions, is it possible to fix this in a new edition so that we don't break backward compatibility? |
Does macro hygiene simply not work with respect to static identifiers in our model of syntax expansion?
For example:
I would have hoped that my use of the name
value
in the macrofoo
is irrelevant to the use of the namevalue
in the body ofmain
.But currently one gets:
This is a shame because the box-desugaring #22181 expands into a
{ ... let value = ...; ... }
, and there is a static binding ofvalue
in src/test/run-pass/drop-struct-as-object.rsThe text was updated successfully, but these errors were encountered: