dtolnay / watt

Runtime for executing procedural macros as WebAssembly
Apache License 2.0
1.29k stars 28 forks source link

`cargo watt` subcommand #41

Open jakobhellermann opened 4 years ago

jakobhellermann commented 4 years ago

I made a cargo subcommand called cargo watt, which aims to improve the tooling listed in the README.

Currently, it does two things:

  1. Compile a proc-macro crate (locally, from git or from crates.io) and generate a crate which exposes the compiled wasm
  2. Verify that that wasm file was compiled from some source

Initially I wanted to replace

#[proc_macro]
pub fn the_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    /* ... */
}

with

#[no_mangle]
pub extern "C" fn the_macro(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    the_macro_inner(input.into().into()
}
pub fn the_macro_inner(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    /* ... */
}

but that doesn't work because Into does not exist in wasm.

So my solution was to just replace the TokenStreams and hope for the best, while also using a patched version of syn which basically just has all instances of proc_macro replaced with proc_macro2.

This actually works for quite a few crates (e.g. serde-derive, typed-builder, tracing-attributes) but it doesn't for some other ones (everything depending on synstructure and some others).

Now I am wondering: Is it fundamentally impossible to provide the From-impls because proc-macro just doesn't exist in wasm, or would it be possible to do this transformation in some other way?

dtolnay commented 4 years ago

Nice!

Yeah proc_macro::TokenStream can't exist except inside code built with --crate-type proc-macro. That is why proc-macro2 exists.

jakobhellermann commented 4 years ago

I see. I assume it is not possible to [patch] proc-macro itself? Then I guess search+replace and hope for the best is the best approach for cargo watt.