+ /// Saves the provided span into the metadata of
+ /// *the crate we are currently compiling*, which must
+ /// be a proc-macro crate. This id can be passed to
+ /// `recover_proc_macro_span` when our current crate
+ /// is *run* as a proc-macro.
+ ///
+ /// Let's suppose that we have two crates - `my_client`
+ /// and `my_proc_macro`. The `my_proc_macro` crate
+ /// contains a procedural macro `my_macro`, which
+ /// is implemented as: `quote! { "hello" }`
+ ///
+ /// When we *compile* `my_proc_macro`, we will execute
+ /// the `quote` proc-macro. This will save the span of
+ /// "hello" into the metadata of `my_proc_macro`. As a result,
+ /// the body of `my_proc_macro` (after expansion) will end
+ /// up containg a call that looks like this:
+ /// `proc_macro::Ident::new("hello", proc_macro::Span::recover_proc_macro_span(0))`
+ ///
+ /// where `0` is the id returned by this function.
+ /// When `my_proc_macro` *executes* (during the compilation of `my_client`),
+ /// the call to `recover_proc_macro_span` will load the corresponding
+ /// span from the metadata of `my_proc_macro` (which we have access to,
+ /// since we've loaded `my_proc_macro` from disk in order to execute it).
+ /// In this way, we have obtained a span pointing into `my_proc_macro`
+ fn save_span(&mut self, mut span: Self::Span) -> usize {
+ // Throw away the `SyntaxContext`, since we currently
+ // skip serializing `SyntaxContext`s for proc-macro crates
+ span = span.with_ctxt(rustc_span::SyntaxContext::root());
+ self.sess.save_proc_macro_span(span)
+ }
+ fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
+ let resolver = self.resolver;
+ let krate = self.krate;
+ let expn_id = self.expn_id;
+ *self.rebased_spans.entry(id).or_insert_with(|| {
+ let raw_span = resolver.get_proc_macro_quoted_span(krate, id);
+ // Ignore the deserialized `SyntaxContext` entirely.
+ // FIXME: Preserve the macro backtrace from the serialized span
+ // For example, if a proc-macro crate has code like
+ // `macro_one!() -> macro_two!() -> quote!()`, we might
+ // want to 'concatenate' this backtrace with the backtrace from
+ // our current call site.
+ raw_span.with_def_site_ctxt(expn_id)
+ })
+ }