mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Record proc macro harness order for use during metadata deserialization
Fixes #68690 When we generate the proc macro harness, we now explicitly recorder the order in which we generate entries. We then use this ordering data to deserialize the correct proc-macro-data from the crate metadata.
This commit is contained in:
parent
61d9231ff2
commit
51a16e574a
@ -140,6 +140,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
|||||||
trait_impls: _,
|
trait_impls: _,
|
||||||
body_ids: _,
|
body_ids: _,
|
||||||
modules: _,
|
modules: _,
|
||||||
|
proc_macros: _,
|
||||||
} = *krate;
|
} = *krate;
|
||||||
|
|
||||||
alloc_hir_dep_nodes(
|
alloc_hir_dep_nodes(
|
||||||
|
@ -530,6 +530,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let module = self.lower_mod(&c.module);
|
let module = self.lower_mod(&c.module);
|
||||||
let attrs = self.lower_attrs(&c.attrs);
|
let attrs = self.lower_attrs(&c.attrs);
|
||||||
let body_ids = body_ids(&self.bodies);
|
let body_ids = body_ids(&self.bodies);
|
||||||
|
let proc_macros = c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id]).collect();
|
||||||
|
|
||||||
self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
|
self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
|
||||||
|
|
||||||
@ -546,6 +547,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
body_ids,
|
body_ids,
|
||||||
trait_impls: self.trait_impls,
|
trait_impls: self.trait_impls,
|
||||||
modules: self.modules,
|
modules: self.modules,
|
||||||
|
proc_macros,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,15 @@ use rustc_span::hygiene::AstPass;
|
|||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
use syntax::ast::{self, Ident};
|
use std::cell::RefCell;
|
||||||
|
use syntax::ast::{self, Ident, NodeId};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::expand::is_proc_macro_attr;
|
use syntax::expand::is_proc_macro_attr;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::visit::{self, Visitor};
|
use syntax::visit::{self, Visitor};
|
||||||
|
|
||||||
struct ProcMacroDerive {
|
struct ProcMacroDerive {
|
||||||
|
id: NodeId,
|
||||||
trait_name: ast::Name,
|
trait_name: ast::Name,
|
||||||
function_name: Ident,
|
function_name: Ident,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -27,6 +29,7 @@ enum ProcMacroDefType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ProcMacroDef {
|
struct ProcMacroDef {
|
||||||
|
id: NodeId,
|
||||||
function_name: Ident,
|
function_name: Ident,
|
||||||
span: Span,
|
span: Span,
|
||||||
def_type: ProcMacroDefType,
|
def_type: ProcMacroDefType,
|
||||||
@ -69,9 +72,6 @@ pub fn inject(
|
|||||||
if has_proc_macro_decls || is_proc_macro_crate {
|
if has_proc_macro_decls || is_proc_macro_crate {
|
||||||
visit::walk_crate(&mut collect, &krate);
|
visit::walk_crate(&mut collect, &krate);
|
||||||
}
|
}
|
||||||
// NOTE: If you change the order of macros in this vec
|
|
||||||
// for any reason, you must also update 'raw_proc_macro'
|
|
||||||
// in src/librustc_metadata/decoder.rs
|
|
||||||
let macros = collect.macros;
|
let macros = collect.macros;
|
||||||
|
|
||||||
if !is_proc_macro_crate {
|
if !is_proc_macro_crate {
|
||||||
@ -86,7 +86,8 @@ pub fn inject(
|
|||||||
return krate;
|
return krate;
|
||||||
}
|
}
|
||||||
|
|
||||||
krate.module.items.push(mk_decls(&mut cx, ¯os));
|
let decls = mk_decls(&mut krate, &mut cx, ¯os);
|
||||||
|
krate.module.items.push(decls);
|
||||||
|
|
||||||
krate
|
krate
|
||||||
}
|
}
|
||||||
@ -181,6 +182,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||||||
|
|
||||||
if self.in_root && item.vis.node.is_pub() {
|
if self.in_root && item.vis.node.is_pub() {
|
||||||
self.macros.push(ProcMacro::Derive(ProcMacroDerive {
|
self.macros.push(ProcMacro::Derive(ProcMacroDerive {
|
||||||
|
id: item.id,
|
||||||
span: item.span,
|
span: item.span,
|
||||||
trait_name: trait_ident.name,
|
trait_name: trait_ident.name,
|
||||||
function_name: item.ident,
|
function_name: item.ident,
|
||||||
@ -200,6 +202,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||||||
fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
|
fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
|
||||||
if self.in_root && item.vis.node.is_pub() {
|
if self.in_root && item.vis.node.is_pub() {
|
||||||
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
||||||
|
id: item.id,
|
||||||
span: item.span,
|
span: item.span,
|
||||||
function_name: item.ident,
|
function_name: item.ident,
|
||||||
def_type: ProcMacroDefType::Attr,
|
def_type: ProcMacroDefType::Attr,
|
||||||
@ -218,6 +221,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||||||
fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
|
fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
|
||||||
if self.in_root && item.vis.node.is_pub() {
|
if self.in_root && item.vis.node.is_pub() {
|
||||||
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
||||||
|
id: item.id,
|
||||||
span: item.span,
|
span: item.span,
|
||||||
function_name: item.ident,
|
function_name: item.ident,
|
||||||
def_type: ProcMacroDefType::Bang,
|
def_type: ProcMacroDefType::Bang,
|
||||||
@ -357,7 +361,15 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||||||
// // ...
|
// // ...
|
||||||
// ];
|
// ];
|
||||||
// }
|
// }
|
||||||
fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
|
fn mk_decls(
|
||||||
|
ast_krate: &mut ast::Crate,
|
||||||
|
cx: &mut ExtCtxt<'_>,
|
||||||
|
macros: &[ProcMacro],
|
||||||
|
) -> P<ast::Item> {
|
||||||
|
// We're the ones filling in this Vec,
|
||||||
|
// so it should be empty to start with
|
||||||
|
assert!(ast_krate.proc_macros.is_empty());
|
||||||
|
|
||||||
let expn_id = cx.resolver.expansion_for_ast_pass(
|
let expn_id = cx.resolver.expansion_for_ast_pass(
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
AstPass::ProcMacroHarness,
|
AstPass::ProcMacroHarness,
|
||||||
@ -376,6 +388,12 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
|
|||||||
let attr = cx.ident_of("attr", span);
|
let attr = cx.ident_of("attr", span);
|
||||||
let bang = cx.ident_of("bang", span);
|
let bang = cx.ident_of("bang", span);
|
||||||
|
|
||||||
|
let krate_ref = RefCell::new(ast_krate);
|
||||||
|
|
||||||
|
// We add NodeIds to 'krate.proc_macros' in the order
|
||||||
|
// that we generate expressions. The position of each NodeId
|
||||||
|
// in the 'proc_macros' Vec corresponds to its position
|
||||||
|
// in the static array that will be generated
|
||||||
let decls = {
|
let decls = {
|
||||||
let local_path =
|
let local_path =
|
||||||
|sp: Span, name| cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]));
|
|sp: Span, name| cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]));
|
||||||
@ -385,19 +403,26 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
|
|||||||
macros
|
macros
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| match m {
|
.map(|m| match m {
|
||||||
ProcMacro::Derive(cd) => cx.expr_call(
|
ProcMacro::Derive(cd) => {
|
||||||
|
krate_ref.borrow_mut().proc_macros.push(cd.id);
|
||||||
|
cx.expr_call(
|
||||||
span,
|
span,
|
||||||
proc_macro_ty_method_path(custom_derive),
|
proc_macro_ty_method_path(custom_derive),
|
||||||
vec![
|
vec![
|
||||||
cx.expr_str(cd.span, cd.trait_name),
|
cx.expr_str(cd.span, cd.trait_name),
|
||||||
cx.expr_vec_slice(
|
cx.expr_vec_slice(
|
||||||
span,
|
span,
|
||||||
cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>(),
|
cd.attrs
|
||||||
|
.iter()
|
||||||
|
.map(|&s| cx.expr_str(cd.span, s))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
),
|
),
|
||||||
local_path(cd.span, cd.function_name),
|
local_path(cd.span, cd.function_name),
|
||||||
],
|
],
|
||||||
),
|
)
|
||||||
|
}
|
||||||
ProcMacro::Def(ca) => {
|
ProcMacro::Def(ca) => {
|
||||||
|
krate_ref.borrow_mut().proc_macros.push(ca.id);
|
||||||
let ident = match ca.def_type {
|
let ident = match ca.def_type {
|
||||||
ProcMacroDefType::Attr => attr,
|
ProcMacroDefType::Attr => attr,
|
||||||
ProcMacroDefType::Bang => bang,
|
ProcMacroDefType::Bang => bang,
|
||||||
|
@ -635,6 +635,9 @@ pub struct Crate<'hir> {
|
|||||||
/// A list of modules written out in the order in which they
|
/// A list of modules written out in the order in which they
|
||||||
/// appear in the crate. This includes the main crate module.
|
/// appear in the crate. This includes the main crate module.
|
||||||
pub modules: BTreeMap<HirId, ModuleItems>,
|
pub modules: BTreeMap<HirId, ModuleItems>,
|
||||||
|
/// A list of proc macro HirIds, written out in the order in which
|
||||||
|
/// they are declared in the static array generated by proc_macro_harness.
|
||||||
|
pub proc_macros: Vec<HirId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crate<'hir> {
|
impl Crate<'hir> {
|
||||||
|
@ -637,10 +637,6 @@ impl<'a, 'tcx> CrateMetadata {
|
|||||||
fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
|
fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
|
||||||
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
|
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
|
||||||
// with items in 'raw_proc_macros'.
|
// with items in 'raw_proc_macros'.
|
||||||
// NOTE: If you update the order of macros in 'proc_macro_data' for any reason,
|
|
||||||
// you must also update src/librustc_builtin_macros/proc_macro_harness.rs
|
|
||||||
// Failing to do so will result in incorrect data being associated
|
|
||||||
// with proc macros when deserialized.
|
|
||||||
let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
|
let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
|
||||||
&self.raw_proc_macros.unwrap()[pos]
|
&self.raw_proc_macros.unwrap()[pos]
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ use std::path::Path;
|
|||||||
use std::u32;
|
use std::u32;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::expand::is_proc_macro_attr;
|
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
@ -1328,13 +1327,7 @@ impl EncodeContext<'tcx> {
|
|||||||
let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
|
let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
|
||||||
if is_proc_macro {
|
if is_proc_macro {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
Some(self.lazy(tcx.hir().krate().items.values().filter_map(|item| {
|
Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner)))
|
||||||
if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) {
|
|
||||||
Some(item.hir_id.owner)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ impl<'a> Parser<'a> {
|
|||||||
attrs: self.parse_inner_attributes()?,
|
attrs: self.parse_inner_attributes()?,
|
||||||
module: self.parse_mod_items(&token::Eof, lo)?,
|
module: self.parse_mod_items(&token::Eof, lo)?,
|
||||||
span: lo.to(self.token.span),
|
span: lo.to(self.token.span),
|
||||||
|
// Filled in by proc_macro_harness::inject()
|
||||||
|
proc_macros: Vec::new(),
|
||||||
});
|
});
|
||||||
krate
|
krate
|
||||||
}
|
}
|
||||||
|
@ -429,6 +429,7 @@ pub struct Crate {
|
|||||||
pub module: Mod,
|
pub module: Mod,
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub proc_macros: Vec<NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possible values inside of compile-time attribute lists.
|
/// Possible values inside of compile-time attribute lists.
|
||||||
|
@ -989,7 +989,7 @@ pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
||||||
visit_clobber(krate, |Crate { module, attrs, span }| {
|
visit_clobber(krate, |Crate { module, attrs, span, proc_macros }| {
|
||||||
let item = P(Item {
|
let item = P(Item {
|
||||||
ident: Ident::invalid(),
|
ident: Ident::invalid(),
|
||||||
attrs,
|
attrs,
|
||||||
@ -1004,11 +1004,11 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
|||||||
let len = items.len();
|
let len = items.len();
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
let module = Mod { inner: span, items: vec![], inline: true };
|
let module = Mod { inner: span, items: vec![], inline: true };
|
||||||
Crate { module, attrs: vec![], span }
|
Crate { module, attrs: vec![], span, proc_macros }
|
||||||
} else if len == 1 {
|
} else if len == 1 {
|
||||||
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
|
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
|
||||||
match kind {
|
match kind {
|
||||||
ItemKind::Mod(module) => Crate { module, attrs, span },
|
ItemKind::Mod(module) => Crate { module, attrs, span, proc_macros },
|
||||||
_ => panic!("visitor converted a module to not a module"),
|
_ => panic!("visitor converted a module to not a module"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,6 +9,19 @@ extern crate proc_macro;
|
|||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
macro_rules! make_attr_macro {
|
||||||
|
($name:ident) => {
|
||||||
|
/// Generated doc comment
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn $name(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_attr_macro!(first_attr);
|
||||||
|
make_attr_macro!(second_attr);
|
||||||
|
|
||||||
/// a proc-macro that swallows its input and does nothing.
|
/// a proc-macro that swallows its input and does nothing.
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn some_proc_macro(_input: TokenStream) -> TokenStream {
|
pub fn some_proc_macro(_input: TokenStream) -> TokenStream {
|
||||||
|
@ -26,3 +26,11 @@ pub use some_macros::some_proc_attr;
|
|||||||
// @has proc_macro/derive.SomeDerive.html
|
// @has proc_macro/derive.SomeDerive.html
|
||||||
// @has - 'a derive attribute that adds nothing to its input.'
|
// @has - 'a derive attribute that adds nothing to its input.'
|
||||||
pub use some_macros::SomeDerive;
|
pub use some_macros::SomeDerive;
|
||||||
|
|
||||||
|
// @has proc_macro/attr.first_attr.html
|
||||||
|
// @has - 'Generated doc comment'
|
||||||
|
pub use some_macros::first_attr;
|
||||||
|
|
||||||
|
// @has proc_macro/attr.second_attr.html
|
||||||
|
// @has - 'Generated doc comment'
|
||||||
|
pub use some_macros::second_attr;
|
||||||
|
@ -1 +1 @@
|
|||||||
{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}
|
{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]}
|
||||||
|
Loading…
Reference in New Issue
Block a user