/rust-proc-macro-without-dependencies

Creating a proc macro in rust without any dependencies

Primary LanguageRust

rust-proc-macro-without-dependencies

This repo shows an example of how to create a proc macro in rust without any dependencies. The default_derive crate provides a proc macro, OurDefault, which re-implements the builtin Default macro.

Credits

The logic in this crate was written by referencing nanoserde's parsing logic and influenced by my rants on the rust internals forum.

Support

The intent is not to cover all possible scenarios, but instead to provide a minimal reference for what I believe is the most common usecase of a simple proc macro: a struct with named fields, no lifetimes, and no generic parameters. It currently does not support any of the following scenarios:

Enums

#[derive(OurDefault)]
enum Foo {
    Bar,
    Baz
}

Unit struct

struct Foo;

(ok, this is just me being lazy and not wanting to complicate the example)

Unnamed structs

struct Foo(String, usize, u32);

Any visibility modifiers that are not just pub

pub(crate) struct Foo { bar: String }

Lifetimes, references, generic parameters

pub(crate) struct Foo<'a, T> { bar: &'a T }

Attributes

#[repr(C)]
pub(crate) struct Foo { bar: String }
#[my_custom_attribute]
pub(crate) struct Foo { bar: String }
pub(crate) struct Foo { #[my_custom_attribute] bar: String }

Output

The default_derive_tester test application will simply test to ensure that the result of TestStruct::our_default() matches Default::default(). Ths emitted tokens look like:

pub struct TestStruct {
    foo: String,
    pub bar: usize,
}
#[automatically_derived]
impl crate::OurDefault for TestStruct {
    fn our_default() -> Self {
        TestStruct {
            foo: Default::default(),
            bar: Default::default(),
        }
    }
}