macro_rules! quote_spanned { ($span:expr=> $($tt: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 highlighted 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.