proc_quote

Macro quote_spanned

Source
macro_rules! quote_spanned {
    ($($proc_macro:tt)*) => { ... };
}
Expand description

Same as quote!, but applies a given span to all tokens originating within the macro invocation.

§Syntax

A span expression of type Span, followed by =>, followed by the tokens to quote. The span expression should be brief – use a variable for anything more than a few characters. There should be no space before the => token.

let span = /* ... */;

// On one line, use parentheses.
let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init)));

// On multiple lines, place the span at the top and use braces.
let tokens = quote_spanned! {span=>
    Box::into_raw(Box::new(#init))
};

The lack of space before the => should look jarring to Rust programmers and this is intentional. The formatting is designed to be visibly off-balance and draw the eye a particular way, due to the span expression being evaluated in the context of the procedural macro and the remaining tokens being evaluated in the generated code.

§Hygiene

Any interpolated tokens preserve the Span information provided by their ToTokens implementation. Tokens that originate within the quote_spanned! invocation are spanned with the given span argument.

§Example

The following procedural macro code uses quote_spanned! to assert that a particular Rust type implements the Sync trait so that references can be safely shared between threads.

let ty_span = ty.span();
let assert_sync = quote_spanned! {ty_span=>
    struct _AssertSync where #ty: Sync;
};

If the assertion fails, the user will see an error like the following. The input span of their type is hightlighted in the error.

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

In this example it is important for the where-clause to be spanned with the line/column information of the user’s input type so that error messages are placed appropriately by the compiler. But it is also incredibly important that Sync resolves at the macro definition site and not the macro call site. If we resolve Sync at the same span that the user’s type is going to be resolved, then they could bypass our check by defining their own trait named Sync that is implemented for their type.