Description
Something in the range bb42071...f9b0897, likely #46343 (CC @jseyfried), broke Servo.
We have a #[dom_struct]
attribute implemented in a dom_struct
crate like this:
#[proc_macro_attribute]
pub fn dom_struct(args: TokenStream, input: TokenStream) -> TokenStream {
if !args.is_empty() {
panic!("#[dom_struct] takes no arguments");
}
let attributes = quote! {
#[derive(DenyPublicFields, DomObject, JSTraceable, MallocSizeOf)]
#[must_root]
#[repr(C)]
};
iter::once(attributes).chain(iter::once(input)).collect()
}
Each of the derives is defined in a respective crate. The script
crate depends on all of these crates and uses #[dom_struct]
. Some of the derives generate code that reference items defined in script
. For example, #[derive(DomObject)]
implements the script::dom::bindings::refector::DomObject
trait.
Since rustc 1.24.0-nightly (f9b0897 2017-12-02), every use of #[dom_struct]
fails with:
error[E0433]: failed to resolve. Could not find `js` in `{{root}}`
--> components/script/dom/attr.rs:28:1
|
28 | #[dom_struct]
| ^^^^^^^^^^^^^ Could not find `js` in `{{root}}`
error[E0433]: failed to resolve. Could not find `dom` in `{{root}}`
--> components/script/dom/attr.rs:28:1
|
28 | #[dom_struct]
| ^^^^^^^^^^^^^ Could not find `dom` in `{{root}}`
error[E0433]: failed to resolve. Could not find `js` in `{{root}}`
--> components/script/dom/attr.rs:28:1
|
28 | #[dom_struct]
| ^^^^^^^^^^^^^ Could not find `js` in `{{root}}`
error[E0433]: failed to resolve. Could not find `malloc_size_of` in `{{root}}`
--> components/script/dom/attr.rs:28:1
|
28 | #[dom_struct]
| ^^^^^^^^^^^^^ Could not find `malloc_size_of` in `{{root}}`
I suppose that these errors come from code generated by the derives, and that {{root}}
refers to the root of the dom_struct
crate where the #[derive(…)]
tokens come from. Indeed, the js
and dom
are not an cannot be available there, they’re in the script
crate which depends on dom_struct
.
We can work around this by erasing hygiene data in the #[derive(…)]
tokens:
--- a/components/dom_struct/lib.rs
+++ b/components/dom_struct/lib.rs
@@ -17,7 +17,9 @@ pub fn dom_struct(args: TokenStream, input: TokenStream) -> TokenStream {
let attributes = quote! {
#[derive(DenyPublicFields, DomObject, JSTraceable, MallocSizeOf)]
#[must_root]
#[repr(C)]
};
+ let attributes = attributes.to_string().parse().unwrap();
iter::once(attributes).chain(iter::once(input)).collect()
}
… but this seems like a valid pattern that shouldn’t necessitate such hacks.