rustc_interface: Add a new query pre_configure
It partially expands crate attributes before the main expansion pass (without modifying the crate), and the produced preliminary crate attribute list is used for querying a few attributes that are required very early. Crate-level cfg attributes are then expanded normally during the main expansion pass, like attributes on any other nodes.
This commit is contained in:
parent
f26da39e04
commit
aca1b1e0b3
12 changed files with 108 additions and 84 deletions
|
@ -3,7 +3,6 @@ use crate::interface::{Compiler, Result};
|
|||
use crate::proc_macro_decls;
|
||||
use crate::util;
|
||||
|
||||
use ast::CRATE_NODE_ID;
|
||||
use rustc_ast::{self as ast, visit};
|
||||
use rustc_borrowck as mir_borrowck;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
|
@ -76,22 +75,14 @@ pub fn register_plugins<'a>(
|
|||
sess: &'a Session,
|
||||
metadata_loader: &'a dyn MetadataLoader,
|
||||
register_lints: impl Fn(&Session, &mut LintStore),
|
||||
krate: &mut ast::Crate,
|
||||
pre_configured_attrs: &[ast::Attribute],
|
||||
crate_name: Symbol,
|
||||
) -> Result<LintStore> {
|
||||
sess.time("attributes_injection", || {
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
krate,
|
||||
&sess.parse_sess,
|
||||
&sess.opts.unstable_opts.crate_attr,
|
||||
)
|
||||
});
|
||||
|
||||
let features = rustc_expand::config::features(sess, krate, CRATE_NODE_ID);
|
||||
// these need to be set "early" so that expansion sees `quote` if enabled.
|
||||
let features = rustc_expand::config::features(sess, pre_configured_attrs);
|
||||
sess.init_features(features);
|
||||
|
||||
let crate_types = util::collect_crate_types(sess, &krate.attrs);
|
||||
let crate_types = util::collect_crate_types(sess, pre_configured_attrs);
|
||||
sess.init_crate_types(crate_types);
|
||||
|
||||
let stable_crate_id = StableCrateId::new(
|
||||
|
@ -117,8 +108,9 @@ pub fn register_plugins<'a>(
|
|||
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
|
||||
register_lints(sess, &mut lint_store);
|
||||
|
||||
let registrars = sess
|
||||
.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate.attrs));
|
||||
let registrars = sess.time("plugin_loading", || {
|
||||
plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
|
||||
});
|
||||
sess.time("plugin_registration", || {
|
||||
let mut registry = plugin::Registry { lint_store: &mut lint_store };
|
||||
for registrar in registrars {
|
||||
|
@ -173,19 +165,29 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
|
|||
/// harness if one is to be provided, injection of a dependency on the
|
||||
/// standard library and prelude, and name resolution.
|
||||
#[instrument(level = "trace", skip(krate, resolver))]
|
||||
fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>) -> ast::Crate {
|
||||
fn configure_and_expand(
|
||||
mut krate: ast::Crate,
|
||||
pre_configured_attrs: &[ast::Attribute],
|
||||
resolver: &mut Resolver<'_, '_>,
|
||||
) -> ast::Crate {
|
||||
let tcx = resolver.tcx();
|
||||
let sess = tcx.sess;
|
||||
let lint_store = unerased_lint_store(tcx);
|
||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||
pre_expansion_lint(sess, lint_store, tcx.registered_tools(()), &krate, crate_name);
|
||||
let lint_check_node = (&krate, pre_configured_attrs);
|
||||
pre_expansion_lint(sess, lint_store, tcx.registered_tools(()), lint_check_node, crate_name);
|
||||
rustc_builtin_macros::register_builtin_macros(resolver);
|
||||
|
||||
sess.time("crate_injection", || {
|
||||
rustc_builtin_macros::standard_library_imports::inject(&mut krate, resolver, sess)
|
||||
let num_standard_library_imports = sess.time("crate_injection", || {
|
||||
rustc_builtin_macros::standard_library_imports::inject(
|
||||
&mut krate,
|
||||
pre_configured_attrs,
|
||||
resolver,
|
||||
sess,
|
||||
)
|
||||
});
|
||||
|
||||
util::check_attr_crate_type(sess, &krate.attrs, &mut resolver.lint_buffer());
|
||||
util::check_attr_crate_type(sess, pre_configured_attrs, &mut resolver.lint_buffer());
|
||||
|
||||
// Expand all macros
|
||||
krate = sess.time("macro_expand_crate", || {
|
||||
|
@ -222,7 +224,7 @@ fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>)
|
|||
|
||||
// Create the config for macro expansion
|
||||
let features = sess.features_untracked();
|
||||
let recursion_limit = get_recursion_limit(&krate.attrs, sess);
|
||||
let recursion_limit = get_recursion_limit(pre_configured_attrs, sess);
|
||||
let cfg = rustc_expand::expand::ExpansionConfig {
|
||||
features: Some(features),
|
||||
recursion_limit,
|
||||
|
@ -235,6 +237,7 @@ fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>)
|
|||
|
||||
let lint_store = LintStoreExpandImpl(lint_store);
|
||||
let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store));
|
||||
ecx.num_standard_library_imports = num_standard_library_imports;
|
||||
// Expand macros now!
|
||||
let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
|
||||
|
||||
|
@ -356,7 +359,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
|
|||
tcx.registered_tools(()),
|
||||
Some(lint_buffer),
|
||||
rustc_lint::BuiltinCombinedEarlyLintPass::new(),
|
||||
&**krate,
|
||||
(&**krate, &*krate.attrs),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -557,9 +560,9 @@ fn resolver_for_lowering<'tcx>(
|
|||
) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
|
||||
let arenas = Resolver::arenas();
|
||||
let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
|
||||
let krate = tcx.crate_for_resolver(()).steal();
|
||||
let mut resolver = Resolver::new(tcx, &krate, &arenas);
|
||||
let krate = configure_and_expand(krate, &mut resolver);
|
||||
let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
|
||||
let mut resolver = Resolver::new(tcx, &pre_configured_attrs, krate.spans.inner_span, &arenas);
|
||||
let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);
|
||||
|
||||
// Make sure we don't mutate the cstore from here on.
|
||||
tcx.untracked().cstore.leak();
|
||||
|
|
|
@ -88,8 +88,9 @@ pub struct Queries<'tcx> {
|
|||
|
||||
dep_graph_future: Query<Option<DepGraphFuture>>,
|
||||
parse: Query<ast::Crate>,
|
||||
pre_configure: Query<(ast::Crate, ast::AttrVec)>,
|
||||
crate_name: Query<Symbol>,
|
||||
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
||||
register_plugins: Query<(ast::Crate, ast::AttrVec, Lrc<LintStore>)>,
|
||||
dep_graph: Query<DepGraph>,
|
||||
// This just points to what's in `gcx_cell`.
|
||||
gcx: Query<&'tcx GlobalCtxt<'tcx>>,
|
||||
|
@ -106,6 +107,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
|
||||
dep_graph_future: Default::default(),
|
||||
parse: Default::default(),
|
||||
pre_configure: Default::default(),
|
||||
crate_name: Default::default(),
|
||||
register_plugins: Default::default(),
|
||||
dep_graph: Default::default(),
|
||||
|
@ -133,17 +135,36 @@ impl<'tcx> Queries<'tcx> {
|
|||
.compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit()))
|
||||
}
|
||||
|
||||
pub fn register_plugins(&self) -> Result<QueryResult<'_, (ast::Crate, Lrc<LintStore>)>> {
|
||||
pub fn pre_configure(&self) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec)>> {
|
||||
self.pre_configure.compute(|| {
|
||||
let mut krate = self.parse()?.steal();
|
||||
|
||||
let sess = self.session();
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
&mut krate,
|
||||
&sess.parse_sess,
|
||||
&sess.opts.unstable_opts.crate_attr,
|
||||
);
|
||||
|
||||
let pre_configured_attrs =
|
||||
rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
|
||||
Ok((krate, pre_configured_attrs))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn register_plugins(
|
||||
&self,
|
||||
) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec, Lrc<LintStore>)>> {
|
||||
self.register_plugins.compute(|| {
|
||||
let crate_name = *self.crate_name()?.borrow();
|
||||
let mut krate = self.parse()?.steal();
|
||||
let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
|
||||
|
||||
let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
|
||||
let lint_store = passes::register_plugins(
|
||||
self.session(),
|
||||
&*self.codegen_backend().metadata_loader(),
|
||||
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
|
||||
&mut krate,
|
||||
&pre_configured_attrs,
|
||||
crate_name,
|
||||
)?;
|
||||
|
||||
|
@ -154,17 +175,17 @@ impl<'tcx> Queries<'tcx> {
|
|||
// called, which happens within passes::register_plugins().
|
||||
self.dep_graph_future().ok();
|
||||
|
||||
Ok((krate, Lrc::new(lint_store)))
|
||||
Ok((krate, pre_configured_attrs, Lrc::new(lint_store)))
|
||||
})
|
||||
}
|
||||
|
||||
fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> {
|
||||
self.crate_name.compute(|| {
|
||||
Ok({
|
||||
let parse_result = self.parse()?;
|
||||
let krate = parse_result.borrow();
|
||||
let pre_configure_result = self.pre_configure()?;
|
||||
let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
|
||||
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
||||
find_crate_name(self.session(), &krate.attrs)
|
||||
find_crate_name(self.session(), pre_configured_attrs)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -188,7 +209,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
||||
self.gcx.compute(|| {
|
||||
let crate_name = *self.crate_name()?.borrow();
|
||||
let (krate, lint_store) = self.register_plugins()?.steal();
|
||||
let (krate, pre_configured_attrs, lint_store) = self.register_plugins()?.steal();
|
||||
|
||||
let sess = self.session();
|
||||
|
||||
|
@ -215,7 +236,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
feed.crate_name(crate_name);
|
||||
|
||||
let feed = tcx.feed_unit_query();
|
||||
feed.crate_for_resolver(tcx.arena.alloc(Steal::new(krate)));
|
||||
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
|
||||
feed.metadata_loader(
|
||||
tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())),
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue