Skip to content
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

Tracking issue for procedural macros and "hygiene 2.0" #54727

Open
alexcrichton opened this issue Oct 1, 2018 · 45 comments
Open

Tracking issue for procedural macros and "hygiene 2.0" #54727

alexcrichton opened this issue Oct 1, 2018 · 45 comments
Assignees
Labels
A-hygiene Area: Macro hygiene A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-proc-macros Area: Procedural macros B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

This is intended to be a tracking issue for enabling procedural macros to have "more hygiene" than the copy/paste hygiene they have today. This is a very vague tracking issue and there's a very long and storied history to this. The intention here though is to create a fresh tracking issue to collect the current state of play, in hopes that we can close some of the much older and very long issues which contain lots of outdated information.

@alexcrichton alexcrichton added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) T-lang Relevant to the language team, which will review and decide on the PR/issue. B-unstable Blocker: Implemented in the nightly compiler and unstable. A-macros-2.0 Area: Declarative macros 2.0 (#39412) C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC labels Oct 1, 2018
@petrochenkov petrochenkov self-assigned this Oct 1, 2018
@petrochenkov
Copy link
Contributor

To give some background, feature(proc_macro_hygiene) tracked by this issue was merged from multiple features (proc_macro_mod, proc_macro_expr, proc_macro_non_items, proc_macro_gen) in #52121.

So, it's pretty heterogeneous and is not even entirely about hygiene.

@petrochenkov
Copy link
Contributor

Copypasting what I wrote in #52121:

None of these features is blocked on hygiene, except for proc_macro_gen.

  • proc_macro_mod is, IIRC, about expanding inner attributes and expanding non-inline modules (mod foo;). I'm not sure why #[my_macro] mod m { ... } with outer attribute and inline module is still gated, I'm not aware of any reasons to not stabilize it.
  • proc_macro_expr/proc_macro_non_items have no reasons to be gated as well and can be stabilized after some implementation audit. Proc macros have well-defined "copy-paste" Span::call_site() hygiene, this includes "unhygienic" use of local variables.
    IIRC, @nrc assumed that additional feature gates would prevent interactions of that copy-paste hygiene with local variables, but that's not true - you can easily expand an item and inject tokens from the outside into its body (e.g. TokenStream::parse does not resolve with Span::call_site() #50050), causing exactly the same interactions.

What is really blocked on hygiene is Span::def_site() and decl_macro (which is also blocked on a ton of other stuff).

@petrochenkov
Copy link
Contributor

proc_macro_gen is more about interactions between Span::call_site hygiene (entirely unhygienic) and macro_rules hygiene (unhygienic except for local variables and labels).

@CodeSandwich
Copy link

This looks like the right branch for this question. Sorry about copy-paste, but I really need to know.

It seems that since rustc 1.30.0-nightly (63d51e89a 2018-09-28) it is no longer possible to traverse code inside module in separate file. If you process mod module;, you get TokenStream containing mod module;, WYSIWYG.

I understand, that this is necessary in order to preserver spans, hygiene and consistency with processed code. Is there or will be any way to work with content of modules in separate files? Its lack may be confusing for end users when trivial refactoring of module organization causes change in macro behavior.

@petrochenkov
Copy link
Contributor

@CodeSandwich
This may be a regression from #52319 perhaps?

cc @tinco

@petrochenkov
Copy link
Contributor

I understand, that this is necessary in order to preserver spans, hygiene and consistency with processed code.

From what I remember, this is an open question.
The transformation mod m; -> mod m { ... } is an expansion of sorts, and we may treat it both as an early expansion (like e.g. #[cfg], which is also expanded before passing the item to attribute-like macros) and as a late expansion (the item is not expanded before being passed to macros).

The "early expansion behavior" looks preferable to me, and this change in behavior looks like a bug rather than a fix.

@tinco
Copy link
Contributor

tinco commented Oct 2, 2018

I lack some context, so I can't be certain, what exactly is "process"? If it relies on rustc's pretty printing, then yes this would be a consequence of #52319, and it should be simple to fix by changing the invocation I think. #52319 does two things:

  1. Add information to the AST (a single bool, tracking if a mod is inline)
  2. Make pretty print no longer print the external file if that bool is false

If you need the expanded file, then that should be made explicit in the invocation of the pretty printer.

@petrochenkov
Copy link
Contributor

Yes, the change is likely due to the pretty-printing change.
So it can be fixed either by reverting the change, or making it more fine-grained so it prints the contents regardless of the inline flag if pretty-printing is done "for proc macros" (whatever that means).

@tinco
Copy link
Contributor

tinco commented Oct 2, 2018

If you can point me at the line of code that invokes the pretty printer, I can suggest a fix.

@CodeSandwich
Copy link

CodeSandwich commented Oct 2, 2018

By "processing" I mean parsing TokenStream with Syn to an Item, modifying its content and converting it back to TokenStream. The precise spot of parsing is here and content traversal is there. I haven't dug into implementation of Syn yet, so I can't tell for sure if it uses pretty printing. I've set nightly feature in Syn, which as far as I know skips step of printing and parsing the string again.

@alexcrichton
Copy link
Member Author

I personally feel that what a proc macro receives as input tokens when attached to a module is an open questions, as @petrochenkov said. I do not think that one answer is clearly correct over another (mod foo; vs mod foo { ... }) at this time. That's why it's unstable!

@eddyb
Copy link
Member

eddyb commented Oct 18, 2018

I'm confused why proc macros expanding to macro_rules! definitions is gated.
(especially when the new macros are only invoked by other expanded items)

@petrochenkov
Copy link
Contributor

petrochenkov commented Oct 18, 2018

@eddyb
Well, the answer is "not enough confidence in correctness of hygiene interactions between transparent (procedural on stable) and semi-transparent (macro_rules) macros".

I hoped to at least get rid of the "context transplantation trick" before stabilizing it, but got distracted by the edition stuff.

It generally works though, I'm not aware of any specific bugs manifesting in normal cases.

@petrochenkov
Copy link
Contributor

$crate in generated macros concerns me in particular.
(I don't remember whether it works correctly now, need to test.)

bors added a commit to rust-lang-ci/rust that referenced this issue May 19, 2020
Stabilize fn-like proc macros in expression, pattern and statement positions

I.e. all the positions in which stable `macro_rules` macros are supported.

Depends on rust-lang#68716 ("Stabilize `Span::mixed_site`").

cc rust-lang#54727
cc rust-lang#54727 (comment)

Stabilization report: rust-lang#68717 (comment).
flip1995 pushed a commit to flip1995/rust-clippy that referenced this issue May 19, 2020
Stabilize fn-like proc macros in expression, pattern and statement positions

I.e. all the positions in which stable `macro_rules` macros are supported.

Depends on rust-lang/rust#68716 ("Stabilize `Span::mixed_site`").

cc rust-lang/rust#54727
cc rust-lang/rust#54727 (comment)

Stabilization report: rust-lang/rust#68717 (comment).
@Aaron1011 Aaron1011 added the A-proc-macros Area: Procedural macros label May 21, 2020
phansch pushed a commit to phansch/rust-clippy that referenced this issue May 24, 2020
Stabilize fn-like proc macros in expression, pattern and statement positions

I.e. all the positions in which stable `macro_rules` macros are supported.

Depends on rust-lang/rust#68716 ("Stabilize `Span::mixed_site`").

cc rust-lang/rust#54727
cc rust-lang/rust#54727 (comment)

Stabilization report: rust-lang/rust#68717 (comment).
RalfJung added a commit to RalfJung/rust that referenced this issue May 24, 2020
…ark-Simulacrum

bootstrap: propagate test-args to miri and clippy test suites

For Miri I verified this works. For clippy, unfortunately it doesn't seem to work as a stage 0 tool:
```
./x.py --stage 0 test src/tools/clippy --test-args init
```
gives
```
   Compiling clippy-mini-macro-test v0.2.0 (/home/r/src/rust/rustc.3/src/tools/clippy/mini-macro)
error[E0658]: procedural macros cannot be expanded to expressions
  --> src/tools/clippy/mini-macro/src/lib.rs:11:5
   |
11 | /     quote!(
12 | |         #[allow(unused)]
13 | |         fn needless_take_by_value(s: String) {
14 | |             println!("{}", s.len());
...  |
24 | |         }
25 | |     )
   | |_____^
   |
   = note: see issue rust-lang#54727 <rust-lang#54727> for more information
   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable

   Compiling proc-macro2 v1.0.3
   Compiling syn v1.0.11
error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
error: could not compile `clippy-mini-macro-test`.
```
But propagating `--test-args` to the test suite seems to make sense regardless.
Cc @rust-lang/clippy
psychon added a commit to psychon/x11rb that referenced this issue Dec 1, 2021
A week ago, futures 0.3.18 was released and apparently this does not
work with Rust 1.41.0:

   Compiling xtrace-example v0.0.0 (/home/runner/work/x11rb/x11rb/xtrace-example)
     Running `rustc --edition=2018 --crate-name xtrace_example xtrace-example/src/main.rs --error-format=json --json=diagnostic-rendered-ansi --emit=dep-info,link -C debuginfo=2 --test -C metadata=516abdc358c39888 -C extra-filename=-516abdc358c39888 --out-dir /home/runner/work/x11rb/x11rb/target/debug/deps -C incremental=/home/runner/work/x11rb/x11rb/target/debug/incremental -L dependency=/home/runner/work/x11rb/x11rb/target/debug/deps --extern futures_io=/home/runner/work/x11rb/x11rb/target/debug/deps/libfutures_io-3756b09c8a44e206.rlib --extern futures_util=/home/runner/work/x11rb/x11rb/target/debug/deps/libfutures_util-411815ec4958698e.rlib --extern smol=/home/runner/work/x11rb/x11rb/target/debug/deps/libsmol-b079add982015d84.rlib --extern x11rb=/home/runner/work/x11rb/x11rb/target/debug/deps/libx11rb-768ac55e45ccd24c.rlib`
error[E0658]: procedural macros cannot be expanded to statements
  --> xtrace-example/src/main.rs:90:5
   |
90 |     futures_util::try_join!(future1, future2)?;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: for more information, see rust-lang/rust#54727
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

See https://github.com/psychon/x11rb/runs/4375081831

Signed-off-by: Uli Schlachter <psychon@znc.in>
psychon added a commit to psychon/x11rb that referenced this issue Dec 1, 2021
A week ago, futures 0.3.18 was released and apparently this does not
work with Rust 1.41.0:

   Compiling xtrace-example v0.0.0 (/home/runner/work/x11rb/x11rb/xtrace-example)
     Running `rustc --edition=2018 --crate-name xtrace_example xtrace-example/src/main.rs --error-format=json --json=diagnostic-rendered-ansi --emit=dep-info,link -C debuginfo=2 --test -C metadata=516abdc358c39888 -C extra-filename=-516abdc358c39888 --out-dir /home/runner/work/x11rb/x11rb/target/debug/deps -C incremental=/home/runner/work/x11rb/x11rb/target/debug/incremental -L dependency=/home/runner/work/x11rb/x11rb/target/debug/deps --extern futures_io=/home/runner/work/x11rb/x11rb/target/debug/deps/libfutures_io-3756b09c8a44e206.rlib --extern futures_util=/home/runner/work/x11rb/x11rb/target/debug/deps/libfutures_util-411815ec4958698e.rlib --extern smol=/home/runner/work/x11rb/x11rb/target/debug/deps/libsmol-b079add982015d84.rlib --extern x11rb=/home/runner/work/x11rb/x11rb/target/debug/deps/libx11rb-768ac55e45ccd24c.rlib`
error[E0658]: procedural macros cannot be expanded to statements
  --> xtrace-example/src/main.rs:90:5
   |
90 |     futures_util::try_join!(future1, future2)?;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: for more information, see rust-lang/rust#54727
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

See https://github.com/psychon/x11rb/runs/4375081831

Signed-off-by: Uli Schlachter <psychon@znc.in>
psychon added a commit to psychon/x11rb that referenced this issue Dec 1, 2021
A week ago, futures 0.3.18 was released and apparently this does not
work with Rust 1.41.0:

   Compiling xtrace-example v0.0.0 (/home/runner/work/x11rb/x11rb/xtrace-example)
     Running `rustc --edition=2018 --crate-name xtrace_example xtrace-example/src/main.rs --error-format=json --json=diagnostic-rendered-ansi --emit=dep-info,link -C debuginfo=2 --test -C metadata=516abdc358c39888 -C extra-filename=-516abdc358c39888 --out-dir /home/runner/work/x11rb/x11rb/target/debug/deps -C incremental=/home/runner/work/x11rb/x11rb/target/debug/incremental -L dependency=/home/runner/work/x11rb/x11rb/target/debug/deps --extern futures_io=/home/runner/work/x11rb/x11rb/target/debug/deps/libfutures_io-3756b09c8a44e206.rlib --extern futures_util=/home/runner/work/x11rb/x11rb/target/debug/deps/libfutures_util-411815ec4958698e.rlib --extern smol=/home/runner/work/x11rb/x11rb/target/debug/deps/libsmol-b079add982015d84.rlib --extern x11rb=/home/runner/work/x11rb/x11rb/target/debug/deps/libx11rb-768ac55e45ccd24c.rlib`
error[E0658]: procedural macros cannot be expanded to statements
  --> xtrace-example/src/main.rs:90:5
   |
90 |     futures_util::try_join!(future1, future2)?;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: for more information, see rust-lang/rust#54727
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

See https://github.com/psychon/x11rb/runs/4375081831

Signed-off-by: Uli Schlachter <psychon@znc.in>
@joshtriplett joshtriplett added S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. and removed A-macros-2.0 Area: Declarative macros 2.0 (#39412) labels Jun 8, 2022
@joshtriplett
Copy link
Member

joshtriplett commented Jun 8, 2022

There are a number of features tracked in this issue. It sounds like some have been stabilized, while others (like def_site) haven't. Would it be possible to get a summary of the remaining work needed for proc macro hygiene? (It may also make sense to break this issue up into multiple tracking issues, or alternatively, get an issue with a checklist of other issues.)

@TheButlah
Copy link

TheButlah commented Sep 13, 2022

I came here from: danakj/dynpath#1

But reading this issue, I have very little clue how "non-inline modules in proc macro input" relates to this issue

@antimora
Copy link

antimora commented Feb 2, 2023

I'm looking forward to this feature. Do you have any updates on the progress or timeline for this feature to become stable?

Specifically I would like this subfeature to be released:


error[E0658]: custom attributes cannot be applied to statements

@JohnScience
Copy link
Contributor

JohnScience commented Oct 6, 2023

The users of my qualifier_attr library would benefit from this because then library authors can write

use qualifier_attr::qualifiers;

#[cfg_attr(semver_exempt, qualifiers(pub))]
mod private_mod1;
#[cfg_attr(semver_exempt, qualifiers(pub))]
mod private_mod2;
// ...

instead of

#[cfg(semver_exempt)]
pub mod private_mod1;
#[cfg(not(semver_exempt))]
mod private_mod1;

#[cfg(semver_exempt)]
pub mod private_mod2;
#[cfg(not(semver_exempt))]
mod private_mod2;
// ...

where private_mod1 and private_mod2 are non-inline modules.

JelteF added a commit to JelteF/derive_more that referenced this issue Aug 6, 2024
We can use `rustversion` for this. For some of the tests its still
needed because of this error:

```
error[E0658]: non-inline modules in proc macro input are unstable
  --> tests/error/mod.rs:53:1
   |
53 | mod nightly;
   | ^^^^^^^^^^^^
   |
   = note: see issue #54727 <rust-lang/rust#54727> for more information
```
@fmease fmease added the A-hygiene Area: Macro hygiene label Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-hygiene Area: Macro hygiene A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-proc-macros Area: Procedural macros B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests