Compute proc_macros in resolutions.

This commit is contained in:
Camille GILLOT 2021-07-16 22:22:08 +02:00
parent 635978041d
commit f8efe5d822
12 changed files with 52 additions and 54 deletions

View file

@ -502,13 +502,6 @@ pub struct Crate {
pub attrs: Vec<Attribute>,
pub items: Vec<P<Item>>,
pub span: Span,
/// The order of items in the HIR is unrelated to the order of
/// items in the AST. However, we generate proc macro harnesses
/// based on the AST order, and later refer to these harnesses
/// from the HIR. This field keeps track of the order in which
/// we generated proc macros harnesses, so that we can map
/// HIR proc macros items back to their harness items.
pub proc_macros: Vec<NodeId>,
}
/// Possible values inside of compile-time attribute lists.

View file

@ -1059,7 +1059,7 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
// or make crate visiting first class if necessary.
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
visit_clobber(krate, |Crate { attrs, items, span, proc_macros }| {
visit_clobber(krate, |Crate { attrs, items, span }| {
let item_vis =
Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
let item = P(Item {
@ -1075,13 +1075,11 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
let len = items.len();
if len == 0 {
Crate { attrs: vec![], items: vec![], span, proc_macros }
Crate { attrs: vec![], items: vec![], span }
} else if len == 1 {
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
match kind {
ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
Crate { attrs, items, span, proc_macros }
}
ItemKind::Mod(_, ModKind::Loaded(items, ..)) => Crate { attrs, items, span },
_ => panic!("visitor converted a module to not a module"),
}
} else {

View file

@ -474,9 +474,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
let proc_macros =
c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
for (k, v) in self.resolver.take_trait_map().into_iter() {
if let Some(Some(hir_id)) = self.node_id_to_hir_id.get(k) {
@ -510,7 +507,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
owners: self.owners,
bodies: self.bodies,
modules: self.modules,
proc_macros,
trait_map,
attrs: self.attrs,
};

View file

@ -13,7 +13,6 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use smallvec::smallvec;
use std::cell::RefCell;
struct ProcMacroDerive {
id: NodeId,
@ -90,7 +89,7 @@ pub fn inject(
return krate;
}
let decls = mk_decls(&mut krate, &mut cx, &macros);
let decls = mk_decls(&mut cx, &macros);
krate.items.push(decls);
krate
@ -289,15 +288,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
// // ...
// ];
// }
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());
fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
let expn_id = cx.resolver.expansion_for_ast_pass(
DUMMY_SP,
AstPass::ProcMacroHarness,
@ -316,26 +307,25 @@ fn mk_decls(
let attr = Ident::new(sym::attr, span);
let bang = Ident::new(sym::bang, span);
let krate_ref = RefCell::new(ast_krate);
// We add NodeIds to 'krate.proc_macros' in the order
// We add NodeIds to 'resolver.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 local_path =
|sp: Span, name| cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]));
let proc_macro_ty_method_path = |method| {
let local_path = |cx: &ExtCtxt<'_>, sp: Span, name| {
cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]))
};
let proc_macro_ty_method_path = |cx: &ExtCtxt<'_>, method| {
cx.expr_path(cx.path(span, vec![proc_macro, bridge, client, proc_macro_ty, method]))
};
macros
.iter()
.map(|m| match m {
ProcMacro::Derive(cd) => {
krate_ref.borrow_mut().proc_macros.push(cd.id);
cx.resolver.declare_proc_macro(cd.id);
cx.expr_call(
span,
proc_macro_ty_method_path(custom_derive),
proc_macro_ty_method_path(cx, custom_derive),
vec![
cx.expr_str(cd.span, cd.trait_name),
cx.expr_vec_slice(
@ -345,12 +335,12 @@ fn mk_decls(
.map(|&s| cx.expr_str(cd.span, s))
.collect::<Vec<_>>(),
),
local_path(cd.span, cd.function_name),
local_path(cx, cd.span, cd.function_name),
],
)
}
ProcMacro::Def(ca) => {
krate_ref.borrow_mut().proc_macros.push(ca.id);
cx.resolver.declare_proc_macro(ca.id);
let ident = match ca.def_type {
ProcMacroDefType::Attr => attr,
ProcMacroDefType::Bang => bang,
@ -358,10 +348,10 @@ fn mk_decls(
cx.expr_call(
span,
proc_macro_ty_method_path(ident),
proc_macro_ty_method_path(cx, ident),
vec![
cx.expr_str(ca.span, ca.function_name.name),
local_path(ca.span, ca.function_name),
local_path(cx, ca.span, ca.function_name),
],
)
}

View file

@ -894,6 +894,14 @@ pub trait ResolverExpand {
/// Decodes the proc-macro quoted span in the specified crate, with the specified id.
/// No caching is performed.
fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span;
/// The order of items in the HIR is unrelated to the order of
/// items in the AST. However, we generate proc macro harnesses
/// based on the AST order, and later refer to these harnesses
/// from the HIR. This field keeps track of the order in which
/// we generated proc macros harnesses, so that we can map
/// HIR proc macros items back to their harness items.
fn declare_proc_macro(&mut self, id: NodeId);
}
#[derive(Clone, Default)]

View file

@ -676,9 +676,6 @@ pub struct Crate<'hir> {
/// A list of modules written out in the order in which they
/// appear in the crate. This includes the main crate module.
pub modules: BTreeMap<LocalDefId, 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>,
/// Map indicating what traits are in scope for places where this
/// is relevant; generated by resolve.

View file

@ -324,7 +324,7 @@ pub fn configure_and_expand(
};
let extern_mod_loaded = |ident: Ident, attrs, items, span| {
let krate = ast::Crate { attrs, items, span, proc_macros: vec![] };
let krate = ast::Crate { attrs, items, span };
pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str());
(krate.attrs, krate.items)
};

View file

@ -454,7 +454,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let table = self.tcx.resolutions(()).definitions.def_path_table();
if self.is_proc_macro {
for def_index in std::iter::once(CRATE_DEF_INDEX)
.chain(self.tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))
.chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index))
{
let def_key = self.lazy(table.def_key(def_index));
let def_path_hash = self.lazy(table.def_path_hash(def_index));
@ -1630,7 +1630,8 @@ impl EncodeContext<'a, 'tcx> {
let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied();
let macros = self.lazy(hir.krate().proc_macros.iter().map(|p| p.owner.local_def_index));
let macros =
self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
for (i, span) in spans.into_iter().enumerate() {
let span = self.lazy(span);
@ -1649,13 +1650,14 @@ impl EncodeContext<'a, 'tcx> {
// Normally, this information is encoded when we walk the items
// defined in this crate. However, we skip doing that for proc-macro crates,
// so we manually encode just the information that we need
for proc_macro in &hir.krate().proc_macros {
let id = proc_macro.owner.local_def_index;
let mut name = hir.name(*proc_macro);
let span = hir.span(*proc_macro);
for &proc_macro in &tcx.resolutions(()).proc_macros {
let id = proc_macro;
let proc_macro = hir.local_def_id_to_hir_id(proc_macro);
let mut name = hir.name(proc_macro);
let span = hir.span(proc_macro);
// Proc-macros may have attributes like `#[allow_internal_unstable]`,
// so downstream crates need access to them.
let attrs = hir.attrs(*proc_macro);
let attrs = hir.attrs(proc_macro);
let macro_kind = if tcx.sess.contains_name(attrs, sym::proc_macro) {
MacroKind::Bang
} else if tcx.sess.contains_name(attrs, sym::proc_macro_attribute) {
@ -1673,10 +1675,10 @@ impl EncodeContext<'a, 'tcx> {
bug!("Unknown proc-macro type for item {:?}", id);
};
let mut def_key = self.tcx.hir().def_key(proc_macro.owner);
let mut def_key = self.tcx.hir().def_key(id);
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
let def_id = DefId::local(id);
let def_id = id.to_def_id();
record!(self.tables.def_kind[def_id] <- DefKind::Macro(macro_kind));
record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
record!(self.tables.attributes[def_id] <- attrs);

View file

@ -134,6 +134,9 @@ pub struct ResolverOutputs {
pub extern_prelude: FxHashMap<Symbol, bool>,
pub main_def: Option<MainDefinition>,
pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
pub proc_macros: Vec<LocalDefId>,
}
#[derive(Clone, Copy, Debug)]

View file

@ -26,8 +26,7 @@ impl<'a> Parser<'a> {
/// Parses a source module as a crate. This is the main entry point for the parser.
pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
let (attrs, items, span) = self.parse_mod(&token::Eof)?;
let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`.
Ok(ast::Crate { attrs, items, span, proc_macros })
Ok(ast::Crate { attrs, items, span })
}
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item.

View file

@ -1035,6 +1035,9 @@ pub struct Resolver<'a> {
main_def: Option<MainDefinition>,
trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
proc_macros: Vec<NodeId>,
}
/// Nothing really interesting here; it just provides memory for the rest of the crate.
@ -1400,6 +1403,7 @@ impl<'a> Resolver<'a> {
item_generics_num_lifetimes: Default::default(),
main_def: Default::default(),
trait_impls: Default::default(),
proc_macros: Default::default(),
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
@ -1434,6 +1438,7 @@ impl<'a> Resolver<'a> {
}
pub fn into_outputs(self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
let definitions = self.definitions;
let visibilities = self.visibilities;
let extern_crate_map = self.extern_crate_map;
@ -1458,10 +1463,12 @@ impl<'a> Resolver<'a> {
.collect(),
main_def,
trait_impls: self.trait_impls,
proc_macros,
}
}
pub fn clone_outputs(&self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
ResolverOutputs {
definitions: self.definitions.clone(),
cstore: Box::new(self.cstore().clone()),
@ -1478,6 +1485,7 @@ impl<'a> Resolver<'a> {
.collect(),
main_def: self.main_def.clone(),
trait_impls: self.trait_impls.clone(),
proc_macros,
}
}

View file

@ -466,6 +466,10 @@ impl<'a> ResolverExpand for Resolver<'a> {
fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
self.crate_loader.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
}
fn declare_proc_macro(&mut self, id: NodeId) {
self.proc_macros.push(id)
}
}
impl<'a> Resolver<'a> {