CodeBlanks Logo Icon CodeBlanks

syn and quote

Generate code with the syn and quote crates.

syn and quote

The two basic tools for writing procedural macros:

  • syn: parses a TokenStream into a Rust syntax tree (DeriveInput, ItemFn, Expr...).
  • quote: turns Rust code written inside quote! { .. }, with #variable interpolations, back into a TokenStream.
let ad = &ast.ident;                 // syn::Ident: Kisi
let n = alanlar.len();
let uretilen = quote! {
    impl #ad {
        fn alan_sayisi() -> usize { #n }
    }
};

In the intermediate step the code isn't text but structured tokens; this lets error messages point to the right source location.

Seeing code generation as text

We can see what quote! produces by building the same template with text; in macro debugging, cargo expand shows exactly this:

fn impl_uret(ad: &str, alanlar: &[&str]) -> String {
    format!(
        "impl {ad} {{ fn alan_sayisi() -> usize {{ {} }} }}",
        alanlar.len()
    )
}

Real macros use quote! instead of string concatenation; the text approach is open to quoting, escaping and location problems.

Practice Code from a template

Write the impl_uret function above. Print the result of impl_uret("Kisi", &["ad", "yas"]).

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn impl_uret(ad: &str, alanlar: &[&str]) -> String {
    format!(
        "impl {ad} {{ fn alan_sayisi() -> usize {{ {} }} }}",
        alanlar.len()
    )
}

fn main() {
    println!("{}", impl_uret("Kisi", &["ad", "yas"]));
}

Expected output

impl Kisi { fn alan_sayisi() -> usize { 2 } }

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How should a user error in a macro (e.g. a struct macro applied to an enum) be reported?

  • A compile error at the right location with syn::Error::new_spanned(..).to_compile_error() Correct answer
  • panic!
  • Silently empty output
  • println!

Explanation: A panic also gives a compile error but with a vague location; an error with a span takes the user to the right line.

2 Interpolate a variable

Question
quote! {
    impl ____ad {
        fn alan_sayisi() -> usize { #n }
    }
}
Answer
quote! {
    impl #ad {
        fn alan_sayisi() -> usize { #n }
    }
}

Explanation: Inside quote!, #ad interpolates the ad variable into the code.

3 Tool and output

Term Meaning
syn::parse_macro_input! Syntax tree
quote! TokenStream
cargo expand Expanded code
syn::Error Error with location

All lessons in Advanced