Skip to content

Custom attributes from unstable plugins and procedural macro attributes are not compatible #40001

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

Closed
nox opened this issue Feb 21, 2017 · 24 comments · Fixed by #40039
Closed

Comments

@nox
Copy link
Contributor

nox commented Feb 21, 2017

In servo/servo@master...nox:custom-derive I changed the attribute #[dom_struct] from our plugins crate (a plugin = true crate) into a proc_macro_attribute function. Unfortunately, the plugins crate also defines a whitelisted attribute #[must_root] and using both at the same time fails with the following compile error:

error: macro undefined: `must_root`
   --> /Users/nox/src/servo/components/script/serviceworkerjob.rs:115:1
    |
115 | #[must_root]
    | ^^^^^^^^^^^^
@nox
Copy link
Contributor Author

nox commented Feb 21, 2017

15:25 <SimonSapin> nox: no sure you’ll get a response other than "don’t use a plugin", unfortunately

Note that #[must_root] is crucial in Servo, because that's the only thing that prevents us from doing very bad things with our JS engine garbage collector, as part of the unrooted_must_root plugin. There is currently absolutely no way to write that as something else than a compiler plugin, so "don't use a plugin" isn't a valid answer to this bug.

@abonander
Copy link
Contributor

@nox Does the plugin remove the #[must_root] attribute after it passes over an item?

cc @jseyfried

@nox
Copy link
Contributor Author

nox commented Feb 21, 2017

@abonander Which plugin do you mean? #[dom_struct] and #[must_root] are independent, but the former expands to a bunch of things, including #[must_root]. It should also be noted that both #[must_root] from #[dom_struct] and #[must_root] applied directly (on things which don't have #[dom_struct]`) trigger the error.

@SimonSapin
Copy link
Contributor

This comment was a bit exaggerated, sorry :) The issue looks like some bad interaction between old-style plugins and new-style procedural macros. Given that plugins are on the way out, I’m skeptical that people will be interested in putting in work to fix it.

In the short term, that means we’ll need to keep dom_struct as a plugin as well. (Unless we can make it a macro_rules! macro, though that makes every use site more verbose, wrapping the entire type in an extra pair of {} braces.)

In medium term, the usual advice is to move everything to proc macros instead of plugins. But as far as I understand this doesn’t work for must_root which is tied to a custom lint check.

The "best" solution here would be proper GC support in the language, but it seems that there is still a lot of work to do before that happens. Maybe @pnkfelix can say more.

@keeperofdakeys
Copy link
Contributor

Which nightly were you using for this? There have been some PRs playing with the expansion order recently, which may have fixed/introduced the issue. This is definitely an issue that should be fixed though.

@SimonSapin
Copy link
Contributor

Servo is currently on rustc 1.17.0-nightly (025c328 2017-02-15)

@nox
Copy link
Contributor Author

nox commented Feb 21, 2017

I just tried with (8a1ce40 2017-02-21), it didn't fix the problem.

@nox
Copy link
Contributor Author

nox commented Feb 21, 2017

Actually the error is different now:

error: cannot find attribute macro `must_root` in this scope
   --> /Users/nox/src/servo/components/script/serviceworkerjob.rs:115:1
    |
115 | #[must_root]
    | ^^^^^^^^^^^^

I double checked whether I still do whitelist it, and whether I still have an plugin attribute for the plugin crate, and I'm pretty sure I do.

@nox
Copy link
Contributor Author

nox commented Feb 21, 2017

I pushed the rustup commit to the branch if anyone wants to try.

@keeperofdakeys
Copy link
Contributor

That was simply the error message being updated. If I have some free time tonight, I'll try looking into this. Does #[must_root] still work by itself? Or only not work when it's expanded through the proc_macro_attribute? Also does the order of attributes that #[dom_struct] expands to have any effect?

@nox
Copy link
Contributor Author

nox commented Feb 21, 2017

It doesn't work anywhere, even on structs that don't use #[dom_struct] at all.

@keeperofdakeys
Copy link
Contributor

I did some debugging, and I only start getting this error when I add the proc_macro feature.

@nox
Copy link
Contributor Author

nox commented Feb 22, 2017

Well yes of course. This bug was discovered when #[dom_struct] was made into a procedural macro instead of an old-style compiler plugin.

@abonander
Copy link
Contributor

This is because #![feature(proc_macro)] causes the compiler to consider all non-builtin or plugin attributes as procedural macros, which is why #![feature(proc_macro)] and #![feature(custom_attribute)] are mutually exclusive. This was to avoid major changes to the way expansion works.

Perhaps we can implement associated attributes similar to what custom derive does. @jseyfried What do you think?

@nox
Copy link
Contributor Author

nox commented Feb 22, 2017

@abonander We don't use custom_attribute, so I don't see how that feature is related.

@nox
Copy link
Contributor Author

nox commented Feb 22, 2017

Perhaps we can implement associated attributes similar to what custom derive does. @jseyfried What do you think?

Also note that #[must_root] is not associated to #[dom_struct] or any procedural macro or procedural macro attribute. It's only used as part of a lint, that can't be expressed by any stable code.

@abonander
Copy link
Contributor

Regardless, that's what I believe is causing the problem here. It's trying to eagerly expand attributes as procedural macros because a kind-of chicken-or-egg problem in that part of expansion. I half expected we'd end up dealing with something like this but I was more eager to at least get the basic implementation going so I could use it with my own prototype.

@keeperofdakeys
Copy link
Contributor

I think the right thing to do here is to modify this function to ignore plugin attributes. (It's only called when the proc_macro feature is enabled). Checking that feature_gate.plugin_attributes does not contain the name may be enough.

@abonander
Copy link
Contributor

The problem is that #[must_root] isn't declared anywhere. It only worked without #![feature(custom_attribute)] because the unrooted_must_root lint marked it as used by checking for it on items.

Perhaps it is necessary to require lints to declare any attributes they use.

@nox
Copy link
Contributor Author

nox commented Feb 22, 2017

It's declared and whitelisted in servo_plugins.

@nox
Copy link
Contributor Author

nox commented Feb 22, 2017

@abonander
Copy link
Contributor

Ah, so yeah, that needs to be checked when collecting attributes then.

@jseyfried
Copy link
Contributor

@SimonSapin @nox

The issue looks like some bad interaction between old-style plugins and new-style procedural macros. Given that plugins are on the way out, I’m skeptical that people will be interested in putting in work to fix it.

I think it is important that old-style plugins interact as well as possible with procedural macros to ensure a smooth transition. At a bare minimum, adding #![feature(proc_macro)] should not break any existing uses of old-style plugins. Any issues involving interaction between plugins and procedural macros will be addressed/fixed quickly.

@abonander fixed this in #40039 (@nox @keeperofdakeys thanks for helping debug!).

@nox
Copy link
Contributor Author

nox commented Feb 22, 2017

Thanks @abonander and @keeperofdakeys, and thanks to the Rust team for the neat per-PR nightlies which will allow me to try it in Servo as soon as the PR lands.

bors added a commit that referenced this issue Feb 23, 2017
Don't assume plugin-whitelisted attributes are proc macro attributes

closes #40001
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants