Github Implement span quoting for proc-macros by Aaron1011 · Pull Request #84278...
source link: https://github.com/rust-lang/rust/pull/84278
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
This PR implements span quoting, allowing proc-macros to produce spans
pointing into their own crate. This is used by the unstableproc_macro::quote!
macro, allowing us to get error messages like this:
error[E0412]: cannot find type `MissingType` in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
|
::: $DIR/span-from-proc-macro.rs:8:1
|
LL | #[error_from_attribute]
| ----------------------- in this macro invocation
Here, MissingType
occurs inside the implementation of the proc-macro#[error_from_attribute]
. Previosuly, this would always result in a
span pointing at #[error_from_attribute]
This will make many proc-macro-related error message much more useful -
when a proc-macro generates code containing an error, users will get an
error message pointing directly at that code (within the macro
definition), instead of always getting a span pointing at the macro
invocation site.
This is implemented as follows:
- When a proc-macro crate is being compiled, it causes the
quote!
macro to get run. This saves all of the sapns in the input toquote!
into the metadata of the proc-macro-crate (which we are currently
compiling). Thequote!
macro then expands to a call toproc_macro::Span::recover_proc_macro_span(id)
, whereid
is an
opaque identifier for the span in the crate metadata. - When the same proc-macro crate is run (e.g. it is loaded from disk
and invoked by some consumer crate), the call toproc_macro::Span::recover_proc_macro_span
causes us to load the span
from the proc-macro crate's metadata. The proc-macro then produces aTokenStream
containing aSpan
pointing into the proc-macro crate
itself.
The recursive nature of 'quote!' can be difficult to understand at
first. The file src/test/ui/proc-macro/quote-debug.stdout
shows
the output of the quote!
macro, which should make this eaier to
understand.
This PR also supports custom quoting spans in custom quote macros (e.g.
the quote
crate). All span quoting goes through theproc_macro::quote_span
method, which can be called by a custom quote
macro to perform span quoting. An example of this usage is provided insrc/test/ui/proc-macro/auxiliary/custom-quote.rs
Custom quoting currently has a few limitations:
In order to quote a span, we need to generate a call toproc_macro::Span::recover_proc_macro_span
. However, proc-macros
support renaming the proc_macro
crate, so we can't simply hardcode
this path. Previously, the quote_span
method used the pathcrate::Span
- however, this only works when it is called by the
builtin quote!
macro in the same crate. To support being called from
arbitrary crates, we need access to the name of the proc_macro
crate
to generate a path. This PR adds an additional argument to quote_span
to specify the name of the proc_macro
crate. Howver, this feels kind
of hacky, and we may want to change this before stabilizing anything
quote-related.
Additionally, using quote_span
currently requires enabling theproc_macro_internals
feature. The builtin quote!
macro
has an #[allow_internal_unstable]
attribute, but this won't work for
custom quote implementations. This will likely require some additional
tricks to apply allow_internal_unstable
to the span ofproc_macro::Span::recover_proc_macro_span
.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK