I'm trying to follow this post to get my feet wet with proc macros (Can a procedural macro be debugged as a function?)
I came up with this to just to get a feel for how it all works:
extern crate proc_macro;
use proc_macro2::TokenStream;
use std::str::FromStr;
use syn;
use quote;
fn main() {
let ts = TokenStream::from_str("fn foo() {}").unwrap();
let _ts_str = ts.to_string();
let parsed = syn::parse_macro_input!(ts);
}
But when I run in the Playground I get this error:
error[E0308]: mismatched types
--> src/main.rs:10:18
|
10 | let parsed = syn::parse_macro_input!(ts);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected struct `proc_macro::TokenStream`, found struct `TokenStream2`
| arguments to this function are incorrect
|
note: function defined here
--> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.103/src/parse_macro_input.rs:138:8
|
138 | pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
| ^^^^^
= note: this error originates in the macro `$crate::parse_macro_input` which comes from the expansion of the macro `syn::parse_macro_input` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> src/main.rs:10:18
|
10 | let parsed = syn::parse_macro_input!(ts);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `proc_macro::TokenStream`
|
= note: this error originates in the macro `$crate::parse_macro_input` which comes from the expansion of the macro `syn::parse_macro_input` (in Nightly builds, run with -Z macro-backtrace for more info)
I'm having trouble understanding what is going on, and could use some help. I've tried various typecasting but nothing seems to work.
I know as a Rust newbie I'm kinda jumping into the deep end of the pool here, but it is somewhat unavoidable. I'm running into little issues that I think will be barriers to getting Rust accepted for our application, and I'm trying to forge a path with as little friction as possible to convince our team (and myself) to move away from C/C++ in our embedded application. So I appreciate the help and patience here.
You have a proc_macro2::TokenStream
while the macro is expecting a proc_macro::TokenStream
. Fortunately, they can be converted between each other with the basic From
/Into
traits.
You've not provided a type to parse into. You should have at least some idea of what kind of syntax you're expecting. Here you could use ItemFn
or more generally Item
. Though if you're making a #[derive()]
macro, you'd use DeriveInput
.
From the documentation on parse_macro_input
:
This macro must be called from a function that returns
proc_macro::TokenStream
.
This is because the macro has error handling built-in and will early-exit with a stream containing a compile_error!
if the stream doesn't match the expected input type.
You may run into issues with trying this in a independent binary like you have here since proc_macro
can only be used within a procedural macro invocation. You can replace the macro with parse2
instead if that's what you want.
Here's a complete working example:
use proc_macro2::TokenStream;
use std::str::FromStr;
use syn::ItemFn;
fn main() {
let ts = TokenStream::from_str("fn foo() {}").unwrap();
let parsed = syn::parse2::<ItemFn>(ts).unwrap();
println!("{:?}", parsed);
}
See it working on the playground.