Course contentsShow
← Rust
Lesson 1538 of 1,91013. Metaprogramming with MacrosFree lesson

Generating Code with Quote

You will utilize template-based code generation to safely interpolate Rust constructs into new source files.

In this lesson, you will learn how to use the quote! macro to transform Rust data structures into valid source code safely and expressively.

Beyond String Concatenation

When building procedural macros, you eventually need to emit new Rust code. While you could technically write this as a raw String, that approach is error-prone, handles indentation poorly, and lacks compiler awareness. The quote crate provides a domain-specific language that allows you to write Rust code inside a macro that returns a TokenStream, which the compiler can then safely ingest.

The magic of quote! lies in its ability to interpolate variables directly into the template using the # (splat/interpolation) syntax.

Interpolating Constructs

Consider a scenario where you have parsed an identifier from a function signature and want to generate a corresponding "getter" function. Using quote!, you can inject that identifier into a new structure seamlessly:

use quote::quote;
use proc_macro2::Ident;

fn generate_getter(name: Ident) -> proc_macro2::TokenStream {
    // We treat 'name' as a variable to be injected into the template
    quote! {
        pub fn #name(&self) -> &str {
            &self.#name
        }
    }
}

In this snippet, #name tells the compiler to replace the placeholder with the actual Ident captured earlier. If you have a collection of items (like fields in a struct), quote! also supports repetition:

let field_names = vec![/* list of Idents */];
let expanded = quote! {
    #(
        pub fn #field_names(&self) -> &str {
            &self.#field_names
        }
    )*
};

The #( ... )* syntax functions like a for loop within the quote template, expanding the block once for every element in the sequence. This ensures that the generated code is syntactically sound and correctly formatted.

Why It Matters

By using quote!, you move away from manual token manipulation and toward a declarative template system. Because it operates on TokenStream objects rather than raw text, it preserves span information, ensuring that if your generated code contains an error, the compiler can point to the exact location where the issue originated, maintaining high-quality error messages for the user.

Key Takeaway: The quote! macro provides a type-safe template engine for generating Rust code, using # for variable interpolation and #( ... )* for efficient repetition across code blocks.