### quote! macro example with interpolation Source: https://github.com/dtolnay/quote/blob/master/README.md Shows how to use the quote! macro to build a TokenStream containing a struct definition, an impl block, and an expression, using #generics, #where_clause, #field_ty, #item_ty, #path, and #value for interpolation. ```rust let tokens = quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, phantom: core::marker::PhantomData<#item_ty>, } impl #generics serde::Serialize for SerializeWith #generics #where_clause { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { #path(self.value, serializer) } } SerializeWith { value: #value, phantom: core::marker::PhantomData::<#item_ty>, } }; ``` -------------------------------- ### Implementing IdentFragment for a custom fragment type Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/ident_fragment.md Example of implementing IdentFragment for a custom type that converts hyphens to underscores. The implementation uses fmt::Display on the replaced string, and format_ident! uses it to create an identifier. ```rust use core::fmt; use proc_macro2::Span; use quote::{format_ident, IdentFragment}; struct SnakeCase(&'static str); impl IdentFragment for SnakeCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0.replace('-', "_"), f) } } let id = format_ident!("my_{}", SnakeCase("foo-bar")); assert_eq!(id, "my_foo_bar"); ``` -------------------------------- ### Repetition syntax examples Source: https://github.com/dtolnay/quote/blob/master/README.md Lists four repetition patterns using #(...)* with different separators and content, including no separator, comma separator, additional tokens, and multiple interpolations. Notes the difference between #(#var ,)* and #(#var),* regarding trailing commas. ```rust #(#var)* ``` ```rust #(#var),* ``` ```rust #( struct #var; )* ``` ```rust #( #k => println!("{}", #v), )* ``` -------------------------------- ### quote! macro usage example Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/quote.md Shows a typical quote! invocation that generates a struct definition with generics, where clause, and field types. Interpolation uses #var and repetition uses #(...)* patterns. ```rust quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, phantom: core::marker::PhantomData<#item_ty>, } } ``` -------------------------------- ### Building a small AST with append and append_separated Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/token_stream_ext.md Builds a small AST by hand using `append` and `append_separated`. Defines a `Comma` separator token and a `build_tuple` function that wraps items in parentheses with commas between them. The example asserts the output string is `"(a , b)"`. ```rust use proc_macro2::{Ident, Punct, Spacing, Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; struct Comma; // separator token impl ToTokens for Comma { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Punct::new(',', Spacing::Alone)); } } fn build_tuple(items: &[TokenStream]) -> TokenStream { let mut tokens = TokenStream::new(); tokens.append(Punct::new('(', Spacing::Alone)); tokens.append_separated(items.iter(), Comma); tokens.append(Punct::new(')', Spacing::Alone)); tokens } let a = quote!(a); let b = quote!(b); assert_eq!(build_tuple(&[a, b]).to_string(), "(a , b)"); ``` -------------------------------- ### Syn-crate consumption pattern Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/spanned.md Shows the intended usage pattern via the `syn` crate, using the blanket implementation to get the span of a value that implements `ToTokens`. ```rust use proc_macro2::Span; use quote::spanned::Spanned; use quote::ToTokens; fn span_of(value: &T) -> Span { value.__span() // Blanket impl renders value to tokens and joins first/last span } let ident = proc_macro2::Ident::new("foo", Span::call_site()); assert_eq!(span_of(ident), Span::call_site()); ``` -------------------------------- ### Basic use — spanning generated tokens with user input position Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/quote_spanned.md Example of using quote_spanned! to generate a struct that asserts Sync, with the span taken from a user input type. If the assertion fails, the compiler reports the error at the user's input span. ```rust use proc_macro2::{Span, TokenStream}; use quote::{quote_spanned, ToTokens}; struct Type; // some parsed input type with a span impl Type { fn span(&self) -> Span { Span::call_site() } } impl ToTokens for Type { fn to_tokens(&self, _tokens: &mut TokenStream) {} } let ty = Type; let ty_span = ty.span(); let assert_sync = quote_spanned! {ty_span=> struct _AssertSync where #ty: Sync; }; ``` ```text error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied --> src/main.rs:10:21 | 10 | static ref PTR: *const () = &(); | ^^^^^^^^^ `*const ()` cannot be shared between threads safely ``` -------------------------------- ### Quick orientation: quote! and related macros Source: https://github.com/dtolnay/quote/blob/master/_autodocs/README.md Shows the core syntax of the `quote!` macro, `quote_spanned!`, `format_ident!`, interpolation with `#var`, repetition patterns, and conversion from `proc_macro2::TokenStream` to `proc_macro::TokenStream`. Use this as a quick reference for the library's primary features. ```rust quote! { ... } — TokenStream of quoted tokens (Span::call_site() internals) quote_spanned!(span=> ...) — same, internals spanned with an explicit span format_ident!(...args) — Ident built by formatting (span inherited from first Ident arg) #var — interpolation, requires ToTokens #(...)* #(...),* #(...)sep* — repetition over Vec/slice/BTreeSet/array/Iterator tokens.into() — convert proc_macro2::TokenStream → proc_macro::TokenStream ``` -------------------------------- ### Spanned Source: https://github.com/dtolnay/quote/blob/master/_autodocs/types.md The `Spanned` trait provides a method to get the span of a value. It is exposed via the `quote::spanned` module and is maintained for the `syn` crate. ```APIDOC ## Spanned ### Description Trait for types that can provide a `Span`. Exposed via `quote::spanned` and maintained for the `syn` crate. ### Method Trait ### Endpoint N/A (Rust trait) ### Parameters #### Methods - **__span(&self) -> proc_macro2::Span** (method) - Required - Span of the receiver ### Request Example N/A ### Response #### Success Response (N/A) - **__span** (proc_macro2::Span) - The span of the receiver #### Response Example N/A ### Implementations - `Span` (identity), `DelimSpan` (`join()`), blanket `T: ?Sized + ToTokens` (`first.join(last)` over rendered tokens, or `Span::call_site()` for an empty stream). ``` -------------------------------- ### Generate formatted code in build.rs using quote and prettyplease Source: https://github.com/dtolnay/quote/blob/master/README.md Use this snippet in a build.rs to generate Rust code, parse it into a syntax tree, format it with prettyplease, and write it to the OUT_DIR. Note that hygiene and span information are not retained when tokens are written to a file. ```rust let output = quote! { ... }; let syntax_tree = syn::parse2(output).unwrap(); let formatted = prettyplease::unparse(&syntax_tree); let out_dir = env::var_os("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("out.rs"); fs::write(dest_path, formatted).unwrap(); ``` -------------------------------- ### append_terminated with trailing separators Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/token_stream_ext.md Demonstrates `append_terminated` which appends a terminator after every item, including the last. The example appends commas after each of `1u32`, `2u32`, and `3u32`, resulting in a trailing comma in the output string. ```rust use proc_macro2::{Punct, Spacing, TokenStream}; use quote::{ToTokens, TokenStreamExt}; let mut tokens = TokenStream::new(); tokens.append_terminated([1u32, 2u32, 3u32], Punct::new(',', Spacing::Alone)); assert_eq!(tokens.to_string(), "1u32 , 2u32 , 3u32 ,"); ``` -------------------------------- ### Integer formatting options Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/format_ident.md Shows how to use integer formatting options with `format_ident!` to produce identifiers with decimal, octal, binary, lower hex, and upper hex representations of a number. ```rust use quote::format_ident; let num: u32 = 10; let decimal = format_ident!("Id_{}", num); // Id_10 let octal = format_ident!("Id_{:o}", num); // Id_12 let binary = format_ident!("Id_{:b}", num); // Id_1010 let lower_hex = format_ident!("Id_{:x}", num); // Id_a let upper_hex = format_ident!("Id_{:X}", num); // Id_A ``` -------------------------------- ### Combining quoted fragments with quote! Source: https://github.com/dtolnay/quote/blob/master/README.md Shows how to build a final TokenStream by interpolating tokens from multiple quote! invocations. The tokens produced by quote! implement ToTokens, so they can be interpolated into later quote! invocations. ```rust let type_definition = quote! {...}; let methods = quote! {...}; let tokens = quote! { #type_definition #methods }; ``` -------------------------------- ### Constructing identifiers with syn::Ident::new Source: https://github.com/dtolnay/quote/blob/master/README.md Alternative to format_ident! using syn::Ident::new to build the identifier. Roughly equivalent but will not handle raw identifiers. ```rust let concatenated = format!("_{}", ident); let varname = syn::Ident::new(&concatenated, ident.span()); quote! { let mut #varname = 0; } ``` -------------------------------- ### Constructing identifiers with format_ident! Source: https://github.com/dtolnay/quote/blob/master/README.md Shows the correct way to prepend an underscore to an identifier using the format_ident! macro, which builds a new identifier token with the correct value. ```rust let varname = format_ident!("_{}", ident); quote! { let mut #varname = 0; } ``` -------------------------------- ### Correct method call with turbofish syntax Source: https://github.com/dtolnay/quote/blob/master/README.md Uses <#field_type>::new() to correctly call a constructor on a type from macro input, expanding to >::new() which is valid syntax. ```rust quote! { let value = <#field_type>::new(); } ``` -------------------------------- ### Using format_ident! with Ident arguments Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/ident_fragment.md Shows how IdentFragment strips the r# prefix when formatting Ident arguments. The first assertion verifies that a raw name is formatted without the prefix, and the second shows that using r#{} does not duplicate the prefix. ```rust use proc_macro2::{Ident, Span}; use quote::{format_ident, IdentFragment}; let ident = Ident::new("raw_name", Span::call_site()); // r# prefix is stripped during formatting assert_eq!(format_ident!("{}", ident), "raw_name"); let raw = Ident::new_raw("type", Span::call_site()); assert_eq!(format_ident!("r#{}", raw), "r#type"); // prefix not duplicated ``` -------------------------------- ### Composing identifiers (raw and non-raw) Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/format_ident.md Shows how to compose identifiers using `format_ident!`, including raw identifiers with the `r#` prefix. The `r#` prefix is stripped from `Ident` arguments before formatting and re-applied by `mk_ident`. ```rust use quote::format_ident; let my_ident = format_ident!("My{}", "Ident"); assert_eq!(my_ident, "MyIdent"); let raw = format_ident!("r#Raw"); assert_eq!(raw, "r#Raw"); let my_ident_raw = format_ident!("{}Is{}", my_ident, raw); assert_eq!(my_ident_raw, "MyIdentIsRaw"); ``` -------------------------------- ### Dependency configuration in Cargo.toml Source: https://github.com/dtolnay/quote/blob/master/_autodocs/configuration.md Declares the proc-macro2 dependency with default-features disabled, and dev-dependencies rustversion and trybuild for testing. The trybuild dev-dependency enables the 'diff' feature. ```toml [dependencies] proc-macro2 = { version = "1.0.80", default-features = false } [dev-dependencies] rustversion = "1.0" trybuild = { version = "1.0.108", features = ["diff"] } ``` -------------------------------- ### Incorrect method call with quote! Source: https://github.com/dtolnay/quote/blob/master/README.md Shows an incorrect way to call a constructor on a type from macro input. Fails for types like Vec because the expanded code becomes invalid syntax. ```rust // incorrect quote! { let value = #field_type::new(); } ``` -------------------------------- ### Add quote dependency to Cargo.toml Source: https://github.com/dtolnay/quote/blob/master/README.md Declares the `quote` crate as a dependency in a Cargo.toml file. Use this to include the crate in a Rust project. ```toml [dependencies] quote = "1.0" ``` -------------------------------- ### Supplying a span Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/ident_fragment.md Shows how to override the span method to provide a span for the formatted identifier. format_ident! adopts the span of the first argument whose span() returns Some. ```rust use proc_macro2::{Ident, Span}; use quote::IdentFragment; struct Tagged(Ident); impl IdentFragment for Tagged { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { self.0.fmt(f) } fn span(&self) -> Option { Some(self.0.span()) } } // format_ident! adopts the span of the first argument whose span() is Some let tagged = Tagged(Ident::new("base", Span::call_site())); let derived = quote::format_ident!("{}_field", tagged); assert_eq!(derived.span(), Span::call_site()); ``` -------------------------------- ### Span and DelimSpan receivers Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/spanned.md Demonstrates calling `__span` directly on `Span` and `DelimSpan` receivers, showing that `DelimSpan::__span` returns the joined span of the delimited group. ```rust use proc_macro2::extra::DelimSpan; use proc_macro2::Span; use quote::spanned::Spanned; let s = Span::call_site(); let via_direct: Span = (s).__span(); let d = DelimSpan::from((s, s)); // delimited group span let via_delim: Span = d.__span(); // d.join() ``` -------------------------------- ### Prefixing an identifier for interpolating into quote! Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/format_ident.md Demonstrates prefixing an identifier with `_` using `format_ident!` and interpolating the result into a `quote!` block. Direct string concatenation would not work because `_#ident` remains two separate tokens. ```rust use proc_macro2::{Ident, Span}; use quote::{format_ident, quote}; let ident = Ident::new("i", Span::call_site()); let varname = format_ident!("_{}", ident); let tokens = quote! { let mut #varname = 0; }; ``` -------------------------------- ### ToTokens::into_token_stream Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/to_tokens.md Provided method that consumes self and delegates to to_token_stream. Requires Self: Sized. ```APIDOC ## ToTokens::into_token_stream ### Description Provided method that converts `self` directly into a `TokenStream` object, consuming `self` in the process. It delegates to `to_token_stream`. ### Method `fn into_token_stream(self) -> TokenStream where Self: Sized` ### Parameters None (only `self`) ### Returns `proc_macro2::TokenStream` - The token stream representation of `self`. ### Example ```rust let tokens = value.into_token_stream(); ``` ``` -------------------------------- ### build.rs rustc version checks Source: https://github.com/dtolnay/quote/blob/master/_autodocs/configuration.md Emits cargo:rustc-check-cfg and cargo:rustc-cfg based on the active rustc minor version. The check-cfg is emitted for minor >= 77, and the no_diagnostic_namespace cfg is set for minor < 78. ```rust if minor >= 77 { println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); } // Support for the `#[diagnostic]` tool attribute namespace // https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes if minor < 78 { println!("cargo:rustc-cfg=no_diagnostic_namespace"); } ``` -------------------------------- ### join_spans helper function Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/spanned.md Computes the span for a token stream by joining the first and last token spans. Returns `Span::call_site()` for an empty stream, the single token's span for a single token, and `first.join(last)` for multiple tokens. ```rust fn join_spans(tokens: TokenStream) -> Span { let mut iter = tokens.into_iter().map(|tt| tt.span()); let Some(first) = iter.next() else { return Span::call_site(); }; iter.fold(None, |_prev, next| Some(next)) .and_then(|last| first.join(last)) .unwrap_or(first) } ``` -------------------------------- ### Trait method call with turbofish syntax Source: https://github.com/dtolnay/quote/blob/master/README.md Shows a similar pattern for trait methods, using <#field_type as core::default::Default>::default() to call a trait method on a type from macro input. ```rust quote! { let value = <#field_type as core::default::Default>::default(); } ``` -------------------------------- ### Error case: invalid identifier panics Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/format_ident.md Demonstrates that `format_ident!` panics at runtime if the resulting formatted string is not a valid identifier. The panic originates in `proc_macro2::Ident::new`. ```rust use quote::format_ident; // panics: "Hello World" contains a space and is not a valid identifier let bad = format_ident!("Hello World"); ``` -------------------------------- ### format_ident! macro signature Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/format_ident.md The macro signature for `format_ident!` with two arms: one for a format string only, and one for a format string with additional arguments. It delegates to the hidden `format_ident_impl!` macro. ```rust #[macro_export] macro_rules! format_ident { ($fmt:expr) => { $crate::format_ident_impl!([ $crate::__private::Option::None, $fmt ]) }; ($fmt:expr, $($rest:tt)*) => { $crate::format_ident_impl!([ $crate::__private::Option::None, $fmt ] $($rest)*) }; } ``` -------------------------------- ### quote_spanned! multiple lines syntax Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/quote_spanned.md Shows the multi-line syntax for quote_spanned!, placing the span at the top and using braces. The missing space before => is intentional. ```rust quote_spanned! {span=> Box::into_raw(Box::new(#init)) }; ``` -------------------------------- ### format_ident! macro Source: https://github.com/dtolnay/quote/blob/master/README.md The format_ident! macro provides a convenient utility for constructing identifiers correctly, especially when modifying identifiers from macro input. ```APIDOC ## format_ident! macro ### Description The `format_ident!` macro provides a convenient utility for constructing identifiers correctly, especially when modifying identifiers from macro input. ### Usage ```rust let varname = format_ident!("_{}", ident); quote! { let mut #varname = 0; } ``` ``` -------------------------------- ### Explicit span Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/format_ident.md Shows how to pass an explicit span to `format_ident!` using the `span = my_span` named argument. The span of the final identifier is the span of the first `Ident` argument, falling back to `call_site()` when no identifier argument is provided. ```rust use quote::format_ident; let my_span = proc_macro2::Span::call_site(); let ident = format_ident!("MyIdent", span = my_span); ``` -------------------------------- ### quote! macro definition with four matcher arms Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/quote.md The full macro_rules! definition of quote! from src/lib.rs:493. It has four arms: empty input, single token, two tokens (with special handling for #var), and a general arm for any number of tokens. The general arm delegates to quote_each_token! for linear compile time. ```rust #[macro_export] macro_rules! quote { () => { $crate::__private::TokenStream::new() }; // Special case rule for a single tt, for performance. ($tt:tt) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::quote_token!{$tt _s} _s }}; // Special case rules for two tts, for performance. (# $var:ident) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::ToTokens::to_tokens(&$var, &mut _s); _s }}; ($tt1:tt $tt2:tt) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::quote_token!{$tt1 _s} $crate::quote_token!{$tt2 _s} _s }}; // Rule for any other number of tokens. ($($tt:tt)*) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::quote_each_token!{_s $($tt)*} _s }}; } ``` -------------------------------- ### TokenStreamExt::append Source: https://github.com/dtolnay/quote/blob/master/_autodocs/api-reference/token_stream_ext.md Appends a single token tree to the token stream. The token must implement Into. ```APIDOC ## append ### Description Appends a single token tree to the token stream. ### Method append ### Signature fn append(&mut self, token: U) where U: Into; ### Parameters - **token** (U) - Required - The token tree to append. Must implement Into. ### Return Type () ### Example ```rust use proc_macro2::{Ident, Span, TokenStream}; use quote::TokenStreamExt; let mut tokens = TokenStream::new(); tokens.append(Ident::new("struct", Span::call_site())); ``` ```