Crate proc_macro_hack[][src]

Defining procedural macros

Two crates are required to define a macro.

The declaration crate

This crate is allowed to contain other public things if you need, for example traits or functions or ordinary macros.

https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack

#[macro_use]
extern crate proc_macro_hack;

// This is what allows the users to depend on just your
// declaration crate rather than both crates.
#[allow(unused_imports)]
#[macro_use]
extern crate demo_hack_impl;
#[doc(hidden)]
pub use demo_hack_impl::*;

proc_macro_expr_decl! {
    /// Add one to an expression.
    add_one! => add_one_impl
}

proc_macro_item_decl! {
    /// A function that always returns 2.
    two_fn! => two_fn_impl
}

The implementation crate

This crate must contain nothing but procedural macros. Private helper functions and private modules are fine but nothing can be public.

https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl

#[macro_use]
extern crate proc_macro_hack;

proc_macro_expr_impl! {
    /// Add one to an expression.
    pub fn add_one_impl(input: &str) -> String {
        format!("1 + {}", input)
    }
}

proc_macro_item_impl! {
    /// A function that always returns 2.
    pub fn two_fn_impl(input: &str) -> String {
        format!("fn {}() -> u8 {{ 2 }}", input)
    }
}

Both crates depend on proc-macro-hack:

[dependencies]
proc-macro-hack = "0.4"

Additionally, your implementation crate (but not your declaration crate) is a proc macro:

[lib]
proc-macro = true

Using procedural macros

Users of your crate depend on your declaration crate (not your implementation crate), then use your procedural macros as though it were magic. They even get reasonable error messages if your procedural macro panics.

https://github.com/dtolnay/proc-macro-hack/tree/master/example

#[macro_use]
extern crate demo_hack;

two_fn!(two);

fn main() {
    let nine = add_one!(two()) + add_one!(2 + 3);
    println!("nine = {}", nine);
}

Expansion of expression macros

m!(ARGS)

… expands to …

{
    #[derive(m_impl)]
    #[allow(unused)]
    enum ProcMacroHack {
        Input = (stringify!(ARGS), 0).1,
    }
    proc_macro_call!()
}

… expands to …

{
    macro_rules! proc_macro_call {
        () => { RESULT }
    }
    proc_macro_call!()
}

… expands to …

{
    RESULT
}

Expansion of item macros

m!(ARGS);

… expands to …

#[derive(m_impl)]
#[allow(unused)]
enum ProcMacroHack {
    Input = (stringify!(ARGS), 0).1,
}

… expands to …

RESULT

Macros

proc_macro_expr_decl

Declare a hacky procedural macro that expands to an expression.

proc_macro_expr_impl

Implement a hacky procedural macro that expands to an expression.

proc_macro_item_decl

Declare a hacky procedural macro that expands to items.

proc_macro_item_impl

Implement a hacky procedural macro that expands to items.