feature(proc_macro) breaks attributes on custom derive (original) (raw)

Using #![feature(proc_macro)] in combination with attributes enabled by #[proc_macro_derive(MyTrait, attributes(mycrate))] (e.g. #[mycrate(some_option = "something")]) fails to compile on the current nightly with error: macro undefined: 'mycrate!'.

Definition of custom derive:

#![feature(proc_macro)]

use std::str::FromStr;

extern crate proc_macro; use proc_macro::TokenStream;

#[proc_macro_derive(MyTrait, attributes(mycrate))] pub fn my_macro(_: TokenStream) -> TokenStream { TokenStream::from_str("").unwrap() }

Use which fails:

#![feature(proc_macro)]

#[macro_use] extern crate proc_macro_collision;

#[derive(MyTrait)] #[mycrate(some_option = "something")] struct Foo;

fn main() { }

If #![feature(proc_macro)] is removed, compilation succeeds.

Compiling the above fails with the following output:

error: macro undefined: 'mycrate!'
 --> examples/with.rs:7:1
  |
7 | #[mycrate(some_option = "something")]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Compilation fails on current nightly:

$ rustc --version --verbose rustc 1.16.0-nightly (df8debf6d 2017-01-25) binary: rustc commit-hash: df8debf6d9afc431adbbd8311dcaf2b70eb9762e commit-date: 2017-01-25 host: x86_64-apple-darwin release: 1.16.0-nightly LLVM version: 3.9

However, compilation succeeds on a week old nightly:

$ rustc --version --verbose rustc 1.16.0-nightly (c07a6ae77 2017-01-17) binary: rustc commit-hash: c07a6ae77cd4ceb3cf591d34c5608ca91d1f75d4 commit-date: 2017-01-17 host: x86_64-apple-darwin release: 1.16.0-nightly LLVM version: 3.9

This is probably connected to #[proc_macro_attribute] which was merged in this timeframe (PR), and not the feature flag itself.

serde_derive-based example failing the same way:

#![feature(proc_macro)]

#[macro_use] extern crate serde_derive;

extern crate serde_json;

#[derive(Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields)] struct Point { x: i32, y: i32, }

fn main() { let point = Point { x: 1, y: 2 };

// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();

// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);

// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();

// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);

}