Change:
In I changed the attribute from our crate (a crate) into a function. Unfortunately, the crate also defines a whitelisted attribute and using both at the same time fails with the following compile error:
Note that 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 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.
Does the plugin remove the attribute after it passes over an item? cc
Which plugin do you mean? and are independent, but the former expands to a bunch of things, including . It should also be noted that both from and #[dom_struct]`) trigger the error.
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 as a plugin as well. (Unless we can make it a 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 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 can say more.
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.
Servo is currently on rustc 1.17.0-nightly ( 2017-02-15)
I just tried with ( 2017-02-21), it didn't fix the problem.
Actually the error is different now: I double checked whether I still do whitelist it, and whether I still have an attribute for the plugin crate, and I'm pretty sure I do.
I pushed the rustup commit to the branch if anyone wants to try.
That was simply the error message being updated. If I have some free time tonight, I'll try looking into this. Does still work by itself? Or only not work when it's expanded through the ? Also does the order of attributes that expands to have any effect?
It doesn't work anywhere, even on structs that don't use at all.
I did some debugging, and I only start getting this error when I add the feature.
Well yes of course. This bug was discovered when was made into a procedural macro instead of an old-style compiler plugin.
This is because causes the compiler to consider all non-builtin or plugin attributes as procedural macros, which is why and 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. What do you think?
We don't use , so I don't see how that feature is related.
Also note that is not associated to 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.
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.
I think the right thing to do here is to modify function to ignore plugin attributes. (It's only called when the procmacro feature is enabled). Checking that featuregate.plugin_attributes does not contain the name may be enough.
The problem is that isn't declared anywhere. It only worked without because the lint marked it as used by checking for it on items. Perhaps it is necessary to require lints to declare any attributes they use.
It's declared and whitelisted in .
Ah, so yeah, that needs to be checked when collecting attributes then.
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 should not break any existing uses of old-style plugins. Any issues involving interaction between plugins and procedural macros will be addressed/fixed quickly. fixed this in ( thanks for helping debug!).
Thanks and 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.

Discussion:
fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> { for i in 0..attrs.len() { <ins> if self.session.plugin_attributes.borrow().iter() .any(|&(ref attr_nm, _)| attrs[i].name() == &**attr_nm) { attr::mark_known(&attrs[i]); } </ins> match self.builtin_macros.get(&attrs[i].name()).cloned() { Some(binding) => match *binding.get_macro(self) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {

<ins> // Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(box_syntax, plugin, plugin_registrar, rustc_private)] #![crate_type = "dylib"] #[macro_use] extern crate rustc; extern crate rustc_plugin; extern crate syntax; use rustc_plugin::Registry; use syntax::ext::base::*; use syntax::feature_gate::AttributeType::Whitelisted; use syntax::symbol::Symbol; use rustc::hir; use rustc::hir::intravisit; use rustc::hir::map as hir_map; use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext}; use rustc::ty; use syntax::{ast, codemap}; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box MissingWhitelistedAttrPass); reg.register_attribute("whitelisted_attr".to_string(), Whitelisted); } declare_lint!(MISSING_WHITELISTED_ATTR, Deny, "Checks for missing `whitelisted_attr` attribute"); struct MissingWhitelistedAttrPass; impl LintPass for MissingWhitelistedAttrPass { fn get_lints(&self) -> LintArray { lint_array!(MISSING_WHITELISTED_ATTR) } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { fn check_fn(&mut self, cx: &LateContext<'a, 'tcx>, _: intravisit::FnKind<'tcx>, _: &'tcx hir::FnDecl, _: &'tcx hir::Body, span: codemap::Span, id: ast::NodeId) { let item = match cx.tcx.hir.get(id) { hir_map::Node::NodeItem(item) => item, _ => cx.tcx.hir.expect_item(cx.tcx.hir.get_parent(id)), }; if !item.attrs.iter().any(|a| a.check_name("whitelisted_attr")) { cx.span_lint(MISSING_WHITELISTED_ATTR, span, "Missing 'whitelited_attr' attribute"); } } } </ins>

<ins> // Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // aux-build:issue-40001-plugin.rs #![feature(proc_macro, plugin)] #![plugin(issue_40001_plugin)] #[whitelisted_attr] fn main() {} </ins>