Rollup merge of #64528 - Aaron1011:fix/proc-macro-type, r=alexcrichton
Load proc macro metadata in the correct order. Serialized proc macro metadata is assumed to have a one-to-one correspondence with the entries in static array generated by proc_macro_harness. However, we were previously serializing proc macro metadata in a different order than proc macros were laied out in the static array. This lead to us associating the wrong data with a proc macro when generating documentation, causing Rustdoc to generate incorrect docs for proc macros. This commit keeps track of the order in which we insert proc macros into the generated static array. We use this same order when serializing proc macro metadata, ensuring that we can later associate the metadata for a proc macro with its entry in the static array. Fixes #64251
This commit is contained in:
commit
76d34f3435
@ -489,7 +489,11 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
|
||||
fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
|
||||
// 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/libsyntax_ext/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();
|
||||
&self.raw_proc_macros.unwrap()[pos]
|
||||
}
|
||||
|
@ -20,15 +20,24 @@ struct ProcMacroDerive {
|
||||
attrs: Vec<ast::Name>,
|
||||
}
|
||||
|
||||
enum ProcMacroDefType {
|
||||
Attr,
|
||||
Bang
|
||||
}
|
||||
|
||||
struct ProcMacroDef {
|
||||
function_name: Ident,
|
||||
span: Span,
|
||||
def_type: ProcMacroDefType
|
||||
}
|
||||
|
||||
enum ProcMacro {
|
||||
Derive(ProcMacroDerive),
|
||||
Def(ProcMacroDef)
|
||||
}
|
||||
|
||||
struct CollectProcMacros<'a> {
|
||||
derives: Vec<ProcMacroDerive>,
|
||||
attr_macros: Vec<ProcMacroDef>,
|
||||
bang_macros: Vec<ProcMacroDef>,
|
||||
macros: Vec<ProcMacro>,
|
||||
in_root: bool,
|
||||
handler: &'a errors::Handler,
|
||||
is_proc_macro_crate: bool,
|
||||
@ -46,22 +55,22 @@ pub fn inject(sess: &ParseSess,
|
||||
let ecfg = ExpansionConfig::default("proc_macro".to_string());
|
||||
let mut cx = ExtCtxt::new(sess, ecfg, resolver);
|
||||
|
||||
let (derives, attr_macros, bang_macros) = {
|
||||
let mut collect = CollectProcMacros {
|
||||
derives: Vec::new(),
|
||||
attr_macros: Vec::new(),
|
||||
bang_macros: Vec::new(),
|
||||
in_root: true,
|
||||
handler,
|
||||
is_proc_macro_crate,
|
||||
is_test_crate,
|
||||
};
|
||||
if has_proc_macro_decls || is_proc_macro_crate {
|
||||
visit::walk_crate(&mut collect, &krate);
|
||||
}
|
||||
(collect.derives, collect.attr_macros, collect.bang_macros)
|
||||
let mut collect = CollectProcMacros {
|
||||
macros: Vec::new(),
|
||||
in_root: true,
|
||||
handler,
|
||||
is_proc_macro_crate,
|
||||
is_test_crate,
|
||||
};
|
||||
|
||||
if has_proc_macro_decls || is_proc_macro_crate {
|
||||
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;
|
||||
|
||||
if !is_proc_macro_crate {
|
||||
return krate
|
||||
}
|
||||
@ -74,7 +83,7 @@ pub fn inject(sess: &ParseSess,
|
||||
return krate;
|
||||
}
|
||||
|
||||
krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros));
|
||||
krate.module.items.push(mk_decls(&mut cx, ¯os));
|
||||
|
||||
krate
|
||||
}
|
||||
@ -161,12 +170,12 @@ impl<'a> CollectProcMacros<'a> {
|
||||
};
|
||||
|
||||
if self.in_root && item.vis.node.is_pub() {
|
||||
self.derives.push(ProcMacroDerive {
|
||||
self.macros.push(ProcMacro::Derive(ProcMacroDerive {
|
||||
span: item.span,
|
||||
trait_name: trait_ident.name,
|
||||
function_name: item.ident,
|
||||
attrs: proc_attrs,
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
let msg = if !self.in_root {
|
||||
"functions tagged with `#[proc_macro_derive]` must \
|
||||
@ -180,10 +189,11 @@ impl<'a> CollectProcMacros<'a> {
|
||||
|
||||
fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
|
||||
if self.in_root && item.vis.node.is_pub() {
|
||||
self.attr_macros.push(ProcMacroDef {
|
||||
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
||||
span: item.span,
|
||||
function_name: item.ident,
|
||||
});
|
||||
def_type: ProcMacroDefType::Attr
|
||||
}));
|
||||
} else {
|
||||
let msg = if !self.in_root {
|
||||
"functions tagged with `#[proc_macro_attribute]` must \
|
||||
@ -197,10 +207,11 @@ impl<'a> CollectProcMacros<'a> {
|
||||
|
||||
fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
|
||||
if self.in_root && item.vis.node.is_pub() {
|
||||
self.bang_macros.push(ProcMacroDef {
|
||||
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
||||
span: item.span,
|
||||
function_name: item.ident,
|
||||
});
|
||||
def_type: ProcMacroDefType::Bang
|
||||
}));
|
||||
} else {
|
||||
let msg = if !self.in_root {
|
||||
"functions tagged with `#[proc_macro]` must \
|
||||
@ -322,9 +333,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
||||
// }
|
||||
fn mk_decls(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
custom_derives: &[ProcMacroDerive],
|
||||
custom_attrs: &[ProcMacroDef],
|
||||
custom_macros: &[ProcMacroDef],
|
||||
macros: &[ProcMacro],
|
||||
) -> P<ast::Item> {
|
||||
let expn_id = cx.resolver.expansion_for_ast_pass(
|
||||
DUMMY_SP,
|
||||
@ -354,26 +363,32 @@ fn mk_decls(
|
||||
let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
|
||||
proc_macro, bridge, client, proc_macro_ty, method,
|
||||
]));
|
||||
custom_derives.iter().map(|cd| {
|
||||
cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
|
||||
cx.expr_str(cd.span, cd.trait_name),
|
||||
cx.expr_vec_slice(
|
||||
span,
|
||||
cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
|
||||
),
|
||||
local_path(cd.span, cd.function_name),
|
||||
])
|
||||
}).chain(custom_attrs.iter().map(|ca| {
|
||||
cx.expr_call(span, proc_macro_ty_method_path(attr), vec![
|
||||
cx.expr_str(ca.span, ca.function_name.name),
|
||||
local_path(ca.span, ca.function_name),
|
||||
])
|
||||
})).chain(custom_macros.iter().map(|cm| {
|
||||
cx.expr_call(span, proc_macro_ty_method_path(bang), vec![
|
||||
cx.expr_str(cm.span, cm.function_name.name),
|
||||
local_path(cm.span, cm.function_name),
|
||||
])
|
||||
})).collect()
|
||||
macros.iter().map(|m| {
|
||||
match m {
|
||||
ProcMacro::Derive(cd) => {
|
||||
cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
|
||||
cx.expr_str(cd.span, cd.trait_name),
|
||||
cx.expr_vec_slice(
|
||||
span,
|
||||
cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
|
||||
),
|
||||
local_path(cd.span, cd.function_name),
|
||||
])
|
||||
},
|
||||
ProcMacro::Def(ca) => {
|
||||
let ident = match ca.def_type {
|
||||
ProcMacroDefType::Attr => attr,
|
||||
ProcMacroDefType::Bang => bang
|
||||
};
|
||||
|
||||
cx.expr_call(span, proc_macro_ty_method_path(ident), vec![
|
||||
cx.expr_str(ca.span, ca.function_name.name),
|
||||
local_path(ca.span, ca.function_name),
|
||||
])
|
||||
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
|
||||
let decls_static = cx.item_static(
|
||||
|
@ -10,8 +10,19 @@ extern crate some_macros;
|
||||
// @has proc_macro/macro.some_proc_macro.html
|
||||
// @has proc_macro/attr.some_proc_attr.html
|
||||
// @has proc_macro/derive.SomeDerive.html
|
||||
pub use some_macros::{some_proc_macro, some_proc_attr, SomeDerive};
|
||||
|
||||
// @has proc_macro/macro.some_proc_macro.html
|
||||
// @has - 'a proc-macro that swallows its input and does nothing.'
|
||||
pub use some_macros::some_proc_macro;
|
||||
|
||||
// @has proc_macro/macro.reexported_macro.html
|
||||
// @has - 'Doc comment from the original crate'
|
||||
pub use some_macros::reexported_macro;
|
||||
|
||||
// @has proc_macro/attr.some_proc_attr.html
|
||||
// @has - 'a proc-macro attribute that passes its item through verbatim.'
|
||||
pub use some_macros::some_proc_attr;
|
||||
|
||||
// @has proc_macro/derive.SomeDerive.html
|
||||
// @has - 'a derive attribute that adds nothing to its input.'
|
||||
pub use some_macros::SomeDerive;
|
||||
|
Loading…
Reference in New Issue
Block a user