Skip to content

Commit 83ba7dd

Browse files
committed
Stop emitting spans from proc macro compile time in quote expansion
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.
1 parent 8c4db85 commit 83ba7dd

File tree

11 files changed

+5
-118
lines changed

11 files changed

+5
-118
lines changed

compiler/rustc_expand/src/base.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools};
1919
use rustc_parse::{parser, MACRO_ARGUMENTS};
2020
use rustc_session::config::CollapseMacroDebuginfo;
2121
use rustc_session::{parse::ParseSess, Limit, Session};
22-
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
22+
use rustc_span::def_id::{DefId, LocalDefId};
2323
use rustc_span::edition::Edition;
2424
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
2525
use rustc_span::source_map::SourceMap;
@@ -1015,10 +1015,6 @@ pub trait ResolverExpand {
10151015
path: &ast::Path,
10161016
) -> Result<bool, Indeterminate>;
10171017

1018-
/// Decodes the proc-macro quoted span in the specified crate, with the specified id.
1019-
/// No caching is performed.
1020-
fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span;
1021-
10221018
/// The order of items in the HIR is unrelated to the order of
10231019
/// items in the AST. However, we generate proc macro harnesses
10241020
/// based on the AST order, and later refer to these harnesses

compiler/rustc_expand/src/proc_macro_server.rs

-43
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ use rustc_ast::token;
99
use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream};
1010
use rustc_ast::util::literal::escape_byte_str_symbol;
1111
use rustc_ast_pretty::pprust;
12-
use rustc_data_structures::fx::FxHashMap;
1312
use rustc_data_structures::sync::Lrc;
1413
use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
1514
use rustc_parse::lexer::nfc_normalize;
1615
use rustc_parse::parse_stream_from_source_str;
1716
use rustc_session::parse::ParseSess;
18-
use rustc_span::def_id::CrateNum;
1917
use rustc_span::symbol::{self, sym, Symbol};
2018
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span};
2119
use smallvec::{smallvec, SmallVec};
@@ -419,8 +417,6 @@ pub(crate) struct Rustc<'a, 'b> {
419417
def_site: Span,
420418
call_site: Span,
421419
mixed_site: Span,
422-
krate: CrateNum,
423-
rebased_spans: FxHashMap<usize, Span>,
424420
}
425421

426422
impl<'a, 'b> Rustc<'a, 'b> {
@@ -430,8 +426,6 @@ impl<'a, 'b> Rustc<'a, 'b> {
430426
def_site: ecx.with_def_site_ctxt(expn_data.def_site),
431427
call_site: ecx.with_call_site_ctxt(expn_data.call_site),
432428
mixed_site: ecx.with_mixed_site_ctxt(expn_data.call_site),
433-
krate: expn_data.macro_def_id.unwrap().krate,
434-
rebased_spans: FxHashMap::default(),
435429
ecx,
436430
}
437431
}
@@ -781,43 +775,6 @@ impl server::Span for Rustc<'_, '_> {
781775
fn source_text(&mut self, span: Self::Span) -> Option<String> {
782776
self.psess().source_map().span_to_snippet(span).ok()
783777
}
784-
785-
/// Saves the provided span into the metadata of
786-
/// *the crate we are currently compiling*, which must
787-
/// be a proc-macro crate. This id can be passed to
788-
/// `recover_proc_macro_span` when our current crate
789-
/// is *run* as a proc-macro.
790-
///
791-
/// Let's suppose that we have two crates - `my_client`
792-
/// and `my_proc_macro`. The `my_proc_macro` crate
793-
/// contains a procedural macro `my_macro`, which
794-
/// is implemented as: `quote! { "hello" }`
795-
///
796-
/// When we *compile* `my_proc_macro`, we will execute
797-
/// the `quote` proc-macro. This will save the span of
798-
/// "hello" into the metadata of `my_proc_macro`. As a result,
799-
/// the body of `my_proc_macro` (after expansion) will end
800-
/// up containing a call that looks like this:
801-
/// `proc_macro::Ident::new("hello", proc_macro::Span::recover_proc_macro_span(0))`
802-
///
803-
/// where `0` is the id returned by this function.
804-
/// When `my_proc_macro` *executes* (during the compilation of `my_client`),
805-
/// the call to `recover_proc_macro_span` will load the corresponding
806-
/// span from the metadata of `my_proc_macro` (which we have access to,
807-
/// since we've loaded `my_proc_macro` from disk in order to execute it).
808-
/// In this way, we have obtained a span pointing into `my_proc_macro`
809-
fn save_span(&mut self, span: Self::Span) -> usize {
810-
self.psess().save_proc_macro_span(span)
811-
}
812-
813-
fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
814-
let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site);
815-
*self.rebased_spans.entry(id).or_insert_with(|| {
816-
// FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding,
817-
// replace it with a def-site context until we are encoding it properly.
818-
resolver.get_proc_macro_quoted_span(krate, id).with_ctxt(def_site.ctxt())
819-
})
820-
}
821778
}
822779

823780
impl server::Symbol for Rustc<'_, '_> {

compiler/rustc_metadata/src/rmeta/decoder.rs

-9
Original file line numberDiff line numberDiff line change
@@ -1475,15 +1475,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
14751475
self.root.native_libraries.decode((self, sess))
14761476
}
14771477

1478-
fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span {
1479-
self.root
1480-
.tables
1481-
.proc_macro_quoted_spans
1482-
.get(self, index)
1483-
.unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
1484-
.decode((self, sess))
1485-
}
1486-
14871478
fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> + '_ {
14881479
self.root.foreign_modules.decode((self, sess))
14891480
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

-9
Original file line numberDiff line numberDiff line change
@@ -579,15 +579,6 @@ impl CStore {
579579
self.get_crate_data(cnum).num_def_ids()
580580
}
581581

582-
pub fn get_proc_macro_quoted_span_untracked(
583-
&self,
584-
cnum: CrateNum,
585-
id: usize,
586-
sess: &Session,
587-
) -> Span {
588-
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
589-
}
590-
591582
pub fn set_used_recursively(&mut self, cnum: CrateNum) {
592583
let cmeta = self.get_crate_data_mut(cnum);
593584
if !cmeta.used {

compiler/rustc_metadata/src/rmeta/encoder.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1809,10 +1809,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
18091809
let stability = tcx.lookup_stability(CRATE_DEF_ID);
18101810
let macros =
18111811
self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
1812-
for (i, span) in self.tcx.sess.psess.proc_macro_quoted_spans() {
1813-
let span = self.lazy(span);
1814-
self.tables.proc_macro_quoted_spans.set_some(i, span);
1815-
}
18161812

18171813
self.tables.def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
18181814
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));

compiler/rustc_metadata/src/rmeta/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ define_tables! {
453453
// `DefPathTable` up front, since we may only ever use a few
454454
// definitions from any given crate.
455455
def_keys: Table<DefIndex, LazyValue<DefKey>>,
456-
proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
457456
variant_data: Table<DefIndex, LazyValue<VariantData>>,
458457
assoc_container: Table<DefIndex, ty::AssocItemContainer>,
459458
macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,

compiler/rustc_resolve/src/macros.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
2020
use rustc_expand::compile_declarative_macro;
2121
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
2222
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
23-
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
23+
use rustc_hir::def_id::{DefId, LocalDefId};
2424
use rustc_middle::middle::stability;
2525
use rustc_middle::ty::RegisteredTools;
2626
use rustc_middle::ty::{TyCtxt, Visibility};
@@ -437,10 +437,6 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
437437
self.path_accessible(expn_id, path, &[MacroNS])
438438
}
439439

440-
fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
441-
self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.tcx.sess)
442-
}
443-
444440
fn declare_proc_macro(&mut self, id: NodeId) {
445441
self.proc_macros.push(id)
446442
}

compiler/rustc_session/src/parse.rs

-14
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,6 @@ pub struct ParseSess {
227227
pub file_depinfo: Lock<FxIndexSet<Symbol>>,
228228
/// Whether cfg(version) should treat the current release as incomplete
229229
pub assume_incomplete_release: bool,
230-
/// Spans passed to `proc_macro::quote_span`. Each span has a numerical
231-
/// identifier represented by its position in the vector.
232-
proc_macro_quoted_spans: AppendOnlyVec<Span>,
233230
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
234231
pub attr_id_generator: AttrIdGenerator,
235232
}
@@ -264,7 +261,6 @@ impl ParseSess {
264261
env_depinfo: Default::default(),
265262
file_depinfo: Default::default(),
266263
assume_incomplete_release: false,
267-
proc_macro_quoted_spans: Default::default(),
268264
attr_id_generator: AttrIdGenerator::new(),
269265
}
270266
}
@@ -316,14 +312,4 @@ impl ParseSess {
316312
});
317313
});
318314
}
319-
320-
pub fn save_proc_macro_span(&self, span: Span) -> usize {
321-
self.proc_macro_quoted_spans.push(span)
322-
}
323-
324-
pub fn proc_macro_quoted_spans(&self) -> impl Iterator<Item = (usize, Span)> + '_ {
325-
// This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for
326-
// AppendOnlyVec, so we resort to this scheme.
327-
self.proc_macro_quoted_spans.iter_enumerated()
328-
}
329315
}

library/proc_macro/src/bridge/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ macro_rules! with_api {
103103
fn subspan($self: $S::Span, start: Bound<usize>, end: Bound<usize>) -> Option<$S::Span>;
104104
fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span;
105105
fn source_text($self: $S::Span) -> Option<String>;
106-
fn save_span($self: $S::Span) -> usize;
107-
fn recover_proc_macro_span(id: usize) -> $S::Span;
108106
},
109107
Symbol {
110108
fn normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>;

library/proc_macro/src/lib.rs

+1-15
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl Default for TokenStream {
226226
}
227227

228228
#[unstable(feature = "proc_macro_quote", issue = "54722")]
229-
pub use quote::{quote, quote_span};
229+
pub use quote::quote;
230230

231231
fn tree_to_bridge_tree(
232232
tree: TokenTree,
@@ -576,20 +576,6 @@ impl Span {
576576
self.0.source_text()
577577
}
578578

579-
// Used by the implementation of `Span::quote`
580-
#[doc(hidden)]
581-
#[unstable(feature = "proc_macro_internals", issue = "27812")]
582-
pub fn save_span(&self) -> usize {
583-
self.0.save_span()
584-
}
585-
586-
// Used by the implementation of `Span::quote`
587-
#[doc(hidden)]
588-
#[unstable(feature = "proc_macro_internals", issue = "27812")]
589-
pub fn recover_proc_macro_span(id: usize) -> Span {
590-
Span(bridge::client::Span::recover_proc_macro_span(id))
591-
}
592-
593579
diagnostic_method!(error, Level::Error);
594580
diagnostic_method!(warning, Level::Warning);
595581
diagnostic_method!(note, Level::Note);

library/proc_macro/src/quote.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ pub fn quote(stream: TokenStream) -> TokenStream {
6464
if stream.is_empty() {
6565
return quote!(crate::TokenStream::new());
6666
}
67-
let proc_macro_crate = quote!(crate);
6867
let mut after_dollar = false;
6968
let tokens = stream
7069
.into_iter()
@@ -105,7 +104,7 @@ pub fn quote(stream: TokenStream) -> TokenStream {
105104
))),
106105
TokenTree::Ident(tt) => quote!(crate::TokenTree::Ident(crate::Ident::new(
107106
(@ TokenTree::from(Literal::string(&tt.to_string()))),
108-
(@ quote_span(proc_macro_crate.clone(), tt.span())),
107+
crate::Span::def_site(),
109108
))),
110109
TokenTree::Literal(tt) => quote!(crate::TokenTree::Literal({
111110
let mut iter = (@ TokenTree::from(Literal::string(&tt.to_string())))
@@ -115,7 +114,7 @@ pub fn quote(stream: TokenStream) -> TokenStream {
115114
if let (Some(crate::TokenTree::Literal(mut lit)), None) =
116115
(iter.next(), iter.next())
117116
{
118-
lit.set_span((@ quote_span(proc_macro_crate.clone(), tt.span())));
117+
lit.set_span(crate::Span::def_site());
119118
lit
120119
} else {
121120
unreachable!()
@@ -131,11 +130,3 @@ pub fn quote(stream: TokenStream) -> TokenStream {
131130

132131
quote!([(@ tokens)].iter().cloned().collect::<crate::TokenStream>())
133132
}
134-
135-
/// Quote a `Span` into a `TokenStream`.
136-
/// This is needed to implement a custom quoter.
137-
#[unstable(feature = "proc_macro_quote", issue = "54722")]
138-
pub fn quote_span(proc_macro_crate: TokenStream, span: Span) -> TokenStream {
139-
let id = span.save_span();
140-
quote!((@ proc_macro_crate ) ::Span::recover_proc_macro_span((@ TokenTree::from(Literal::usize_unsuffixed(id)))))
141-
}

0 commit comments

Comments
 (0)