-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stop emitting spans from proc macro compile time in quote expansion #125721
base: master
Are you sure you want to change the base?
Conversation
Before this commit if the proc_macro::quote!{} macro was used, the span of each token as written in the source of the proc macro itself would be saved in the crate metadata of the proc macro and then recovered at proc macro runtime to forward this to the macro expansion of the proc macro. This commit stops doing this and instead generates def-site spans for each token. This removes the only case where spans from the proc macro source have a semantic effect on the compilation of crates that use the proc macro. This makes it easier to stop requiring all dependencies of proc macros to be present when using the proc macro. And will make it easier to stop requiring a proc macro to be present when using a crate that used this proc macro internally but doesn't expose it as part of it's public api. The latter is necessary to be able to cross-compile tools that link against rustc internals without requiring to be built as part of rustc with the -Zdual-proc-macro hack. It may also enable using proc macros inside the standard library or it's dependencies without breaking cross-compilation.
r? @davidtwco rustbot has assigned @davidtwco. Use |
@@ -105,7 +104,7 @@ pub fn quote(stream: TokenStream) -> TokenStream { | |||
))), | |||
TokenTree::Ident(tt) => quote!(crate::TokenTree::Ident(crate::Ident::new( | |||
(@ TokenTree::from(Literal::string(&tt.to_string()))), | |||
(@ quote_span(proc_macro_crate.clone(), tt.span())), | |||
crate::Span::def_site(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While Span::def_site()
is unstable, so is quote!{}
. In addition Span::def_site()
is the closest to the behavior before this PR.
This comment has been minimized.
This comment has been minimized.
cc #84278 @Aaron1011 |
rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead. cc @rust-lang/rust-analyzer |
Forgot to mention two extra reasons for removing this:
|
This comment has been minimized.
This comment has been minimized.
This feels like a really unfortunate regression, and I'd like to avoid if at all possible.
Can you elaborate on this? Setting aside hygiene, could we make this 'best-effort' (similar to how we try to load the span source file from disk), where we won't show a span location + backtrace in error messages if the needed proc-macro dependency is missing? I would expect this to be unobserable to proc-macros (expect for the unstable span inspection apis, which I assume would have a similar problem with 'normal' cross-crate spans).
I'm not familiar with how proc-macros and spans are handled in rust-analyzer, but couldn't it keep falling back to
I think you're right - however, I think it could be easily fixed by also encoding a crate number / identifier (and gracefully falling back to |
It could (or well it actually does, though incorrectly, currently we incorrectly return call site hygiene). Though it would be really nice if we could actually have the proper spans here accessible (how ours differ doesn't really matter, the point is that ours will always differ as rustc's spans are generally unusable to us). r-a side issue tracking this rust-lang/rust-analyzer#16464 |
That's something that I hoped to fix eventually. Of course, alternatively, proc macro crates could be redesigned to give a guarantee of never being needed after doing their work and producing some code. E.g. if we have a compiled rlib with some of source code originally generated by proc macros, that rlib won't contain any traces of the proc macro crates used for generation. |
The expansion context (including hygiene) is the exact thing I'm worried about. If you want to preserve just source location we could encode the start and end |
I want to see this implemented and making this easier to implement is one of the goals of this PR. I think with this PR it is doable if the proc macro is marked as private dependency. Proc macros already skip most of their crate metadata generation anyway, so it is hard to accidentally depend on the crate metadata of a proc macro after expansion, other than through spans and expansion contexts. |
9e60ab3
to
f10b7fc
Compare
Some history:
So things were more nuanced than I recalled in #125721 (comment). |
From those threads it's clear that proc-macro crates cannot always be eliminated from the graph.
|
@bjorn3 |
How about removing the expansion context but keeping the source locations for the serialized spans? Foreign source locations are already inlined in the local proc-macro metadata since #73706 if I understand correctly so keeping them avoids regressing diagnostics without being unable to skip loading dependencies of proc macros, but expansion contexts refer to DefId that can't be just inlined as multiple proc-macros could share the same dependency, in which case the DefId has to be the same.
Can macros 2.0 refer to private dependencies? If not all of these cases are disallowed if the proc macro dependency is marked as private, right? |
Yeah, something similar to #73706 would be the best solution for things shown in diagnostics, I think.
Private in which sense? |
Yes
👍 |
☔ The latest upstream changes (presumably #126623) made this pull request unmergeable. Please resolve the merge conflicts. |
@bjorn3 ping from triage - can you post your status on this PR? This PR has not received an update in a few months. |
There is some discussion ongoing in #54722 about how exactly we want quote to behave with respect to spans. |
Before this commit if the proc_macro::quote!{} macro was used, the span of each token as written in the source of the proc macro itself would be saved in the crate metadata of the proc macro and then recovered at proc macro runtime to forward this to the macro expansion of the proc macro. This commit stops doing this and instead generates def-site spans for each token. This removes the only case where spans from the proc macro source have a semantic effect on the compilation of crates that use the proc macro. This makes it easier to stop requiring all dependencies of proc macros to be present when using the proc macro. And will make it easier to stop requiring a proc macro to be present when using a crate that used this proc macro internally but doesn't expose it as part of it's public api. The latter is necessary to be able to cross-compile tools that link against rustc internals without requiring to be built as part of rustc with the -Zdual-proc-macro hack. It may also enable using proc macros inside the standard library or it's dependencies without breaking cross-compilation.