-
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
Hygiene opt-out for idents in expansion of declarative macros #47992
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @petrochenkov (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Could you add all the examples from the PR descriptions as tests? |
@petrochenkov Yep, sounds fair. Also, thoughts on my above comment about use of the syntax in legacy |
Oh, and I think the syntax |
A further question:
|
Okay, my present thoughts are that 3 and 4 should indeed fail. To make them work would mean having the macro parser understand items, which would mean binding it more tightly to the normal parser, and really make a mess of things. |
@alexreg I'm confused as to what it would mean for them to work, even if it would involve reworking the parser. If I understand correctly, in examples 3 and 4 // `main` scope
// vvvvvvv
pub mod foo_mod {
// `foo!` scope
// vvv
pub const BAR: u32 = 123;
} In both cases |
ad66b24
to
c64d318
Compare
@pierzchalski Well, the alternative semantics would be i.e. We have
(The same end result in terms of hygiene as for |
c64d318
to
e7495a9
Compare
@alexreg Ah, I see! Yeah, making scopes semantics-aware sounds like a lot of work. It also means you'd need a way to 'un-lift' any identifiers you expected to use privately: // `main` scope
// vvvvvvv
pub mod foo_mod {
// `main` scope
// vvv
pub fn bar() {
// I want this to be in `foo_mod!` scope
baz();
}
// Perhaps I want this private to `foo_mod!` but
// `pub` because it's used by... other modules generated by `foo_mod!`,
// or something else silly.
pub fn baz() { ... }
} |
If it can be easily prohibited, then let's prohibit it for a start, otherwise any use of the |
Why? |
Yes, ideally we should. |
What is "3 and 4"? |
@petrochenkov The 3rd and 4th code snippets in the starting post (I was also briefly lost on that). |
They should fail then, |
cc https://internals.rust-lang.org/t/pre-rfc-splitting-liftime-into-two-tokens/6716 |
@pierzchalski Exactly. The difficulties outweigh the small benefits and added complexity I think. |
@petrochenkov Sounds good to me. If we can solve the spaces problem mentioned there, it will definitely simplify a lot of code. For now I may hack around it. |
Sure. I'll have a go at this – I don't think it's too hard. |
I think of it in terms of composability. For a metavar |
Okay, tests added (both run-pass & compile-fail) – everything passing locally. r? @jseyfried CC @nikomatsakis too, in case @jseyfried is too busy still (I've noticed a bit of activity from him though). |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
How are we looking now, @petrochenkov / @jseyfried? :-) |
We discussed this in the language team meeting, and we agree that this needs an actual RFC to specify this for review. This is not the kind of thing we should just do without an RFC. |
@joshtriplett Okay. What I'll do then is get @petrochenkov & @jseyfried's feedback now, and then start writing up an RFC including what's been done (and learnt) in this PR, plus future plans. Maybe we can leave this open in the meanwhile, then once that's accepted, we can hopefully get this merged with few changes? |
@alexreg I'd prefer for this PR to be closed in the meantime, otherwise triage would have to check this PR every week. Then when you're ready you can open it again. |
@pietroalbini As long as it can be reopened easily, sure. Hopefully @petrochenkov & @jseyfried will see my above comments anyway, and leave some feedback before I get to writing the RFC. |
pub struct Escaper(pub SyntaxContext); | ||
|
||
impl Folder for Escaper { | ||
fn fold_ident(&mut self, mut ident: Ident) -> Ident { |
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.
Overriding fold_ident
is not necessary, overridden new_span
applies to identifiers as well.
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.
Ah, I see. Why is it necessary in the Folder
implementation for Marker
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.
It isn't necessary there either, it's just something I forgot to remove in #49154.
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.
Okay. :-)
I'm not even sure there's a need in a separate feature gate beyond |
Feedback: the implementation looks good to me, but if lang team thinks it needs an RFC, then it needs an RFC. |
Ok, closing this until an RFC is approved. @alexreg when you're ready to work on this again just click the reopen button |
@pietroalbini |
@pietroalbini It turns out I don't have the rights to reopen my PRs (as I thought), but I'll ping you or someone else when it's time, sure! |
@petrochenkov There's no easy way to get whether we're in legacy mode from within the |
@petrochenkov Also, should the errors be emitted when doing the actual parsing of the macro or the expansion? |
Don't know, looks like no.
Ideally, if some error will be reported at any expansion, then it should be reported at macro definition. |
@petrochenkov Makes sense, thanks. I think we can bail within the |
@petrochenkov Incidentally, do you want to disallow I'm not sure what the error message should be when an interpolated token follows |
Something like "Hygiene opt-out is not supported for macro parameters" or "... on the left side of the macro". |
Hmm, what are interpolated tokens? Something to do with proc macros I seem to recall, but I don’t really know. The term might confuse users, no? |
The problem with this is, we're allowing |
@petrochenkov Pushed new commits anyway, in case you want to have a look. May make another, depending on your answers to the above two queries, but otherwise I'll focus on the RFC now. |
This PR adds basic support for hygiene opt-out for idents during macro expansion. This has been previously discussed in #40847 and #39412.
The syntax involves prefixing idents with the
#
(i.e. pound/hash) character to indicate that the syntax context of the ident should be that of the call site rather than the definition site.The following now compiles and runs as expected:
as does:
but the following does not:
nor does:
Questions:
macro_rules
macros, of course, but should we explicitly disallow the#
syntax in such places? (Currently that is not done.)CC @jseyfried