How to use `proc_macro` on Rust 2018?

I am trying to build a proc-macro crate with Rust 2018 edition. However, I cannot use the proc_macro crate.

My Cargo.toml:

[package]
name = "letrec"
version = "0.1.0"
authors = ["Bruno Zimmermann <brunoczim@gmail.com>"]
edition = "2018"

[lib]
proc-macro = true
crate-type = ["proc-macro"]

[dependencies]
syn = "*"

My src/lib.rs:

use proc_macro::TokenStream;

#[proc_macro]
pub fn letrec(toks: TokenStream) -> TokenStream {
    unimplemented!()
}

And the error:

error[E0432]: unresolved import `proc_macro`                                                                                                                             
 --> src/lib.rs:1:5                                                                                                                                                      
  |                                                                                                                                                                      
1 | use proc_macro::TokenStream;                                                                                                                                         
  |     ^^^^^^^^^^ Could not find `proc_macro` in `{{root}}`                                                                                                             
                                                                                                                                                                         
error: aborting due to previous error

The problem seems to be I cannot declare extern crate proc_macro and I also cannot find another way of declaring it.

EDIT: I have tried also the following, which yields a bizarre error:

use self::proc_macro::TokenStream;

Error:

error[E0432]: unresolved import `self::proc_macro`                                                                                                                       
 --> src/lib.rs:1:11                                                                                                                                                     
  |                                                                                                                                                                      
1 | use self::proc_macro::TokenStream;                                                                                                                                   
  |           ^^^^^^^^^^ Did you mean `crate::registrar::proc_macro`?                                                                                                    
                                                                                                                                                                         
error: aborting due to previous error 

Then, if I try to change it to

use crate::registrar::proc_macro::TokenStream;

I get:

error[E0433]: failed to resolve. Maybe a missing `extern crate registrar;`?                                                                                              
 --> src/lib.rs:1:12                                                                                                                                                     
  |                                                                                                                                                                      
1 | use crate::registrar::proc_macro::TokenStream;                                                                                                                       
  |            ^^^^^^^^^ Maybe a missing `extern crate registrar;`?   

EDIT2: Surprisingly, I can still write extern crate proc_macro;. If I do this, everything works fine, but I have to import crate::proc_macro::TokenStream.

NOTE: using 1.30.0-nightly (887690686 2018-09-27)

This is a (hopefully temporary) situation; since proc_macro isn't declared in Cargo.toml, cargo doesn't tell rustc to look for / link it.

The only crates always available in the crate prelude are std, core, and meta IIRC. (The third is unused for now but there are vague plans that it be used to replace proc_macro as a name more descriptive of what it would be than how it's accomplished.)

I believe the short term plan is for proc_macro = "built-in" to work in the project manifest. (It doesn't currently.)

3 Likes

Yep, for now, you still need extern crate for it.

1 Like

Is this still the state of things on this? (I'm running into this on a migration right now.)

As far as I know, yes.

1 Like

For the reference: Procedural Macros - The Rust Reference

extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro]
pub fn make_answer(_item: TokenStream) -> TokenStream {
    "fn answer() -> u32 { 42 }".parse().unwrap()
}

Yes, it is needed.

3 Likes