Rollup merge of #66791 - cjgillot:arena, r=Mark-Simulacrum

Handle GlobalCtxt directly from librustc_interface query system

This PR constructs the `GlobalCtxt` as a member of the `Queries` in librustc_interface.
This simplifies the code to construct it, at the expense of added complexity in the query control flow.
This allows to handle the arenas directly from librustc_interface.

Based on #66707

r? @Zoxc
This commit is contained in:
Ralf Jung 2019-11-29 22:57:34 +01:00 committed by GitHub
commit 6ea1df2340
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 348 additions and 276 deletions

View File

@ -93,6 +93,7 @@ macro_rules! arena_types {
rustc::hir::def_id::CrateNum
>
>,
[few] hir_forest: rustc::hir::map::Forest,
[few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
syntax::symbol::Symbol,
rustc::hir::def_id::DefId,

View File

@ -200,7 +200,7 @@ pub struct Map<'hir> {
map: HirEntryMap<'hir>,
definitions: &'hir Definitions,
definitions: Definitions,
/// The reverse mapping of `node_to_hir_id`.
hir_to_node_id: FxHashMap<HirId, NodeId>,
@ -267,8 +267,8 @@ impl<'hir> Map<'hir> {
}
#[inline]
pub fn definitions(&self) -> &'hir Definitions {
self.definitions
pub fn definitions(&self) -> &Definitions {
&self.definitions
}
pub fn def_key(&self, def_id: DefId) -> DefKey {
@ -1251,7 +1251,7 @@ impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
pub fn map_crate<'hir>(sess: &crate::session::Session,
cstore: &CrateStoreDyn,
forest: &'hir Forest,
definitions: &'hir Definitions)
definitions: Definitions)
-> Map<'hir> {
let _prof_timer = sess.prof.generic_activity("build_hir_map");
@ -1260,7 +1260,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session,
.map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
let (map, crate_hash) = {
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore);
let mut collector = NodeCollector::root(sess,
&forest.krate,

View File

@ -995,7 +995,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> {
}
pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>,
pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
interners: CtxtInterners<'tcx>,
@ -1170,6 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> {
local_providers: ty::query::Providers<'tcx>,
extern_providers: ty::query::Providers<'tcx>,
arenas: &'tcx AllArenas,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
resolutions: ty::ResolverOutputs,
hir: hir_map::Map<'tcx>,
on_disk_query_result_cache: query::OnDiskCache<'tcx>,
@ -1225,7 +1226,7 @@ impl<'tcx> TyCtxt<'tcx> {
sess: s,
lint_store,
cstore,
arena: WorkerLocal::new(|_| Arena::default()),
arena,
interners,
dep_graph,
prof: s.prof.clone(),

View File

@ -283,121 +283,128 @@ pub fn run_compiler(
return sess.compile_status();
}
compiler.parse()?;
let linker = compiler.enter(|queries| {
let early_exit = || sess.compile_status().map(|_| None);
queries.parse()?;
if let Some(ppm) = &sess.opts.pretty {
if ppm.needs_ast_map() {
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
let expanded_crate = compiler.expansion()?.take().0;
pretty::print_after_hir_lowering(
tcx,
compiler.input(),
&expanded_crate,
if let Some(ppm) = &sess.opts.pretty {
if ppm.needs_ast_map() {
queries.global_ctxt()?.peek_mut().enter(|tcx| {
let expanded_crate = queries.expansion()?.take().0;
pretty::print_after_hir_lowering(
tcx,
compiler.input(),
&expanded_crate,
*ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
Ok(())
})?;
} else {
let krate = queries.parse()?.take();
pretty::print_after_parsing(
sess,
&compiler.input(),
&krate,
*ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
Ok(())
}
return early_exit();
}
if callbacks.after_parsing(compiler) == Compilation::Stop {
return early_exit();
}
if sess.opts.debugging_opts.parse_only ||
sess.opts.debugging_opts.show_span.is_some() ||
sess.opts.debugging_opts.ast_json_noexpand {
return early_exit();
}
{
let (_, lint_store) = &*queries.register_plugins()?.peek();
// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
describe_lints(&sess, &lint_store, true);
return early_exit();
}
}
queries.expansion()?;
if callbacks.after_expansion(compiler) == Compilation::Stop {
return early_exit();
}
queries.prepare_outputs()?;
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1
{
return early_exit();
}
queries.global_ctxt()?;
if sess.opts.debugging_opts.no_analysis ||
sess.opts.debugging_opts.ast_json {
return early_exit();
}
if sess.opts.debugging_opts.save_analysis {
let expanded_crate = &queries.expansion()?.peek().0;
let crate_name = queries.crate_name()?.peek().clone();
queries.global_ctxt()?.peek_mut().enter(|tcx| {
let result = tcx.analysis(LOCAL_CRATE);
time(sess, "save analysis", || {
save::process_crate(
tcx,
&expanded_crate,
&crate_name,
&compiler.input(),
None,
DumpHandler::new(
compiler.output_dir().as_ref().map(|p| &**p), &crate_name
)
)
});
result
// AST will be dropped *after* the `after_analysis` callback
// (needed by the RLS)
})?;
} else {
let krate = compiler.parse()?.take();
pretty::print_after_parsing(
sess,
&compiler.input(),
&krate,
*ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
// Drop AST after creating GlobalCtxt to free memory
mem::drop(queries.expansion()?.take());
}
return sess.compile_status();
}
if callbacks.after_parsing(compiler) == Compilation::Stop {
return sess.compile_status();
}
queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
if sess.opts.debugging_opts.parse_only ||
sess.opts.debugging_opts.show_span.is_some() ||
sess.opts.debugging_opts.ast_json_noexpand {
return sess.compile_status();
}
{
let (_, lint_store) = &*compiler.register_plugins()?.peek();
// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
describe_lints(&sess, &lint_store, true);
return sess.compile_status();
if callbacks.after_analysis(compiler) == Compilation::Stop {
return early_exit();
}
if sess.opts.debugging_opts.save_analysis {
mem::drop(queries.expansion()?.take());
}
queries.ongoing_codegen()?;
if sess.opts.debugging_opts.print_type_sizes {
sess.code_stats.print_type_sizes();
}
let linker = queries.linker()?;
Ok(Some(linker))
})?;
if let Some(linker) = linker {
linker.link()?
}
compiler.expansion()?;
if callbacks.after_expansion(compiler) == Compilation::Stop {
return sess.compile_status();
}
compiler.prepare_outputs()?;
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1
{
return sess.compile_status();
}
compiler.global_ctxt()?;
if sess.opts.debugging_opts.no_analysis ||
sess.opts.debugging_opts.ast_json {
return sess.compile_status();
}
if sess.opts.debugging_opts.save_analysis {
let expanded_crate = &compiler.expansion()?.peek().0;
let crate_name = compiler.crate_name()?.peek().clone();
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
let result = tcx.analysis(LOCAL_CRATE);
time(sess, "save analysis", || {
save::process_crate(
tcx,
&expanded_crate,
&crate_name,
&compiler.input(),
None,
DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name)
)
});
result
// AST will be dropped *after* the `after_analysis` callback
// (needed by the RLS)
})?;
} else {
// Drop AST after creating GlobalCtxt to free memory
mem::drop(compiler.expansion()?.take());
}
compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
if callbacks.after_analysis(compiler) == Compilation::Stop {
return sess.compile_status();
}
if sess.opts.debugging_opts.save_analysis {
mem::drop(compiler.expansion()?.take());
}
compiler.ongoing_codegen()?;
// Drop GlobalCtxt after starting codegen to free memory
mem::drop(compiler.global_ctxt()?.take());
if sess.opts.debugging_opts.print_type_sizes {
sess.code_stats.print_type_sizes();
}
compiler.link()?;
if sess.opts.debugging_opts.perf_stats {
sess.print_perf_stats();
}

View File

@ -1,4 +1,3 @@
use crate::queries::Queries;
use crate::util;
pub use crate::passes::BoxedResolver;
@ -36,7 +35,6 @@ pub struct Compiler {
pub(crate) input_path: Option<PathBuf>,
pub(crate) output_dir: Option<PathBuf>,
pub(crate) output_file: Option<PathBuf>,
pub(crate) queries: Queries,
pub(crate) crate_name: Option<String>,
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
pub(crate) override_queries:
@ -169,7 +167,6 @@ pub fn run_compiler_in_existing_thread_pool<R>(
input_path: config.input_path,
output_dir: config.output_dir,
output_file: config.output_file,
queries: Default::default(),
crate_name: config.crate_name,
register_lints: config.register_lints,
override_queries: config.override_queries,

View File

@ -3,6 +3,7 @@ use crate::util;
use crate::proc_macro_decls;
use log::{info, warn, log_enabled};
use rustc::arena::Arena;
use rustc::dep_graph::DepGraph;
use rustc::hir;
use rustc::hir::lowering::lower_crate;
@ -22,7 +23,7 @@ use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_codegen_utils::link::filename_for_metadata;
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
use rustc_data_structures::sync::{Lrc, Once, ParallelIterator, par_iter, WorkerLocal};
use rustc_errors::PResult;
use rustc_incremental;
use rustc_mir as mir;
@ -739,93 +740,77 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) {
rustc_codegen_ssa::provide_extern(providers);
}
declare_box_region_type!(
pub BoxedGlobalCtxt,
for('tcx),
(&'tcx GlobalCtxt<'tcx>) -> ((), ())
);
pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>);
impl BoxedGlobalCtxt {
impl<'tcx> QueryContext<'tcx> {
pub fn enter<F, R>(&mut self, f: F) -> R
where
F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
F: FnOnce(TyCtxt<'tcx>) -> R,
{
self.access(|gcx| ty::tls::enter_global(gcx, |tcx| f(tcx)))
ty::tls::enter_global(self.0, |tcx| f(tcx))
}
pub fn print_stats(&self) {
self.0.queries.print_stats()
}
}
pub fn create_global_ctxt(
compiler: &Compiler,
pub fn create_global_ctxt<'tcx>(
compiler: &'tcx Compiler,
lint_store: Lrc<lint::LintStore>,
mut hir_forest: hir::map::Forest,
hir_forest: &'tcx hir::map::Forest,
mut resolver_outputs: ResolverOutputs,
outputs: OutputFilenames,
crate_name: &str,
) -> BoxedGlobalCtxt {
let sess = compiler.session().clone();
let codegen_backend = compiler.codegen_backend().clone();
let crate_name = crate_name.to_string();
global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
all_arenas: &'tcx AllArenas,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
) -> QueryContext<'tcx> {
let sess = &compiler.session();
let defs = mem::take(&mut resolver_outputs.definitions);
let override_queries = compiler.override_queries;
let ((), result) = BoxedGlobalCtxt::new(static move || {
let sess = &*sess;
let global_ctxt: Option<GlobalCtxt<'_>>;
let arenas = AllArenas::new();
// Construct the HIR map.
let hir_map = time(sess, "indexing HIR", || {
hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs)
});
let query_result_on_disk_cache = time(sess, "load query result cache", || {
rustc_incremental::load_query_result_cache(sess)
});
let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
let mut extern_providers = local_providers;
default_provide_extern(&mut extern_providers);
codegen_backend.provide_extern(&mut extern_providers);
if let Some(callback) = override_queries {
callback(sess, &mut local_providers, &mut extern_providers);
}
let gcx = TyCtxt::create_global_ctxt(
sess,
lint_store,
local_providers,
extern_providers,
&arenas,
resolver_outputs,
hir_map,
query_result_on_disk_cache,
&crate_name,
&outputs
);
global_ctxt = Some(gcx);
let gcx = global_ctxt.as_ref().unwrap();
ty::tls::enter_global(gcx, |tcx| {
// Do some initialization of the DepGraph that can only be done with the
// tcx available.
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
});
yield BoxedGlobalCtxt::initial_yield(());
box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx));
if sess.opts.debugging_opts.query_stats {
gcx.queries.print_stats();
}
// Construct the HIR map.
let hir_map = time(sess, "indexing HIR", || {
hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs)
});
result
let query_result_on_disk_cache = time(sess, "load query result cache", || {
rustc_incremental::load_query_result_cache(sess)
});
let codegen_backend = compiler.codegen_backend();
let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
let mut extern_providers = local_providers;
default_provide_extern(&mut extern_providers);
codegen_backend.provide_extern(&mut extern_providers);
if let Some(callback) = compiler.override_queries {
callback(sess, &mut local_providers, &mut extern_providers);
}
let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt(
sess,
lint_store,
local_providers,
extern_providers,
&all_arenas,
arena,
resolver_outputs,
hir_map,
query_result_on_disk_cache,
&crate_name,
&outputs
));
// Do some initialization of the DepGraph that can only be done with the tcx available.
ty::tls::enter_global(&gcx, |tcx| {
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
});
QueryContext(gcx)
}
/// Runs the resolution, type-checking, region checking and other

View File

@ -1,17 +1,19 @@
use crate::interface::{Compiler, Result};
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};
use crate::passes::{self, BoxedResolver, QueryContext};
use rustc_incremental::DepGraphFuture;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::util::common::{time, ErrorReported};
use rustc::arena::Arena;
use rustc::hir;
use rustc::lint;
use rustc::session::Session;
use rustc::lint::LintStore;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::ty::steal::Steal;
use rustc::ty::ResolverOutputs;
use rustc::ty::{AllArenas, ResolverOutputs, GlobalCtxt};
use rustc::dep_graph::DepGraph;
use std::cell::{Ref, RefMut, RefCell};
use std::rc::Rc;
@ -44,13 +46,6 @@ impl<T> Query<T> {
.unwrap()
}
/// Returns a stolen query result. Panics if there's already a result.
pub fn give(&self, value: T) {
let mut result = self.result.borrow_mut();
assert!(result.is_none(), "a result already exists");
*result = Some(Ok(value));
}
/// Borrows the query result using the RefCell. Panics if the result is stolen.
pub fn peek(&self) -> Ref<'_, T> {
Ref::map(self.result.borrow(), |r| {
@ -74,24 +69,54 @@ impl<T> Default for Query<T> {
}
}
#[derive(Default)]
pub(crate) struct Queries {
pub struct Queries<'tcx> {
compiler: &'tcx Compiler,
gcx: Once<GlobalCtxt<'tcx>>,
all_arenas: AllArenas,
arena: WorkerLocal<Arena<'tcx>>,
dep_graph_future: Query<Option<DepGraphFuture>>,
parse: Query<ast::Crate>,
crate_name: Query<String>,
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
dep_graph: Query<DepGraph>,
lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
lower_to_hir: Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>,
prepare_outputs: Query<OutputFilenames>,
global_ctxt: Query<BoxedGlobalCtxt>,
global_ctxt: Query<QueryContext<'tcx>>,
ongoing_codegen: Query<Box<dyn Any>>,
link: Query<()>,
}
impl Compiler {
impl<'tcx> Queries<'tcx> {
pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
Queries {
compiler,
gcx: Once::new(),
all_arenas: AllArenas::new(),
arena: WorkerLocal::new(|_| Arena::default()),
dep_graph_future: Default::default(),
parse: Default::default(),
crate_name: Default::default(),
register_plugins: Default::default(),
expansion: Default::default(),
dep_graph: Default::default(),
lower_to_hir: Default::default(),
prepare_outputs: Default::default(),
global_ctxt: Default::default(),
ongoing_codegen: Default::default(),
}
}
fn session(&self) -> &Lrc<Session> {
&self.compiler.sess
}
fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
&self.compiler.codegen_backend()
}
pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
self.queries.dep_graph_future.compute(|| {
self.dep_graph_future.compute(|| {
Ok(if self.session().opts.build_dep_graph() {
Some(rustc_incremental::load_dep_graph(self.session()))
} else {
@ -101,8 +126,8 @@ impl Compiler {
}
pub fn parse(&self) -> Result<&Query<ast::Crate>> {
self.queries.parse.compute(|| {
passes::parse(self.session(), &self.input).map_err(
self.parse.compute(|| {
passes::parse(self.session(), &self.compiler.input).map_err(
|mut parse_error| {
parse_error.emit();
ErrorReported
@ -112,7 +137,7 @@ impl Compiler {
}
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
self.queries.register_plugins.compute(|| {
self.register_plugins.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let krate = self.parse()?.take();
@ -120,7 +145,7 @@ impl Compiler {
let result = passes::register_plugins(
self.session(),
&*self.codegen_backend().metadata_loader(),
self.register_lints
self.compiler.register_lints
.as_ref()
.map(|p| &**p)
.unwrap_or_else(|| empty),
@ -140,8 +165,8 @@ impl Compiler {
}
pub fn crate_name(&self) -> Result<&Query<String>> {
self.queries.crate_name.compute(|| {
Ok(match self.crate_name {
self.crate_name.compute(|| {
Ok(match self.compiler.crate_name {
Some(ref crate_name) => crate_name.clone(),
None => {
let parse_result = self.parse()?;
@ -149,7 +174,7 @@ impl Compiler {
rustc_codegen_utils::link::find_crate_name(
Some(self.session()),
&krate.attrs,
&self.input
&self.compiler.input
)
}
})
@ -159,11 +184,11 @@ impl Compiler {
pub fn expansion(
&self
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
self.queries.expansion.compute(|| {
self.expansion.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let (krate, lint_store) = self.register_plugins()?.take();
passes::configure_and_expand(
self.sess.clone(),
self.session().clone(),
lint_store.clone(),
self.codegen_backend().metadata_loader(),
krate,
@ -175,7 +200,7 @@ impl Compiler {
}
pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
self.queries.dep_graph.compute(|| {
self.dep_graph.compute(|| {
Ok(match self.dep_graph_future()?.take() {
None => DepGraph::new_disabled(),
Some(future) => {
@ -192,15 +217,15 @@ impl Compiler {
}
pub fn lower_to_hir(
&self,
) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
self.queries.lower_to_hir.compute(|| {
&'tcx self,
) -> Result<&Query<(&'tcx hir::map::Forest, Steal<ResolverOutputs>)>> {
self.lower_to_hir.compute(|| {
let expansion_result = self.expansion()?;
let peeked = expansion_result.peek();
let krate = &peeked.0;
let resolver = peeked.1.steal();
let lint_store = &peeked.2;
let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
let hir = resolver.borrow_mut().access(|resolver| {
passes::lower_to_hir(
self.session(),
lint_store,
@ -208,41 +233,47 @@ impl Compiler {
&*self.dep_graph()?.peek(),
&krate
)
})?);
})?;
let hir = self.arena.alloc(hir);
Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
})
}
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
self.queries.prepare_outputs.compute(|| {
self.prepare_outputs.compute(|| {
let expansion_result = self.expansion()?;
let (krate, boxed_resolver, _) = &*expansion_result.peek();
let crate_name = self.crate_name()?;
let crate_name = crate_name.peek();
passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name)
passes::prepare_outputs(
self.session(), self.compiler, &krate, &boxed_resolver, &crate_name
)
})
}
pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
self.queries.global_ctxt.compute(|| {
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
self.global_ctxt.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let outputs = self.prepare_outputs()?.peek().clone();
let lint_store = self.expansion()?.peek().2.clone();
let hir = self.lower_to_hir()?;
let hir = hir.peek();
let (hir_forest, resolver_outputs) = &*hir;
let hir = self.lower_to_hir()?.peek();
let (ref hir_forest, ref resolver_outputs) = &*hir;
Ok(passes::create_global_ctxt(
self,
self.compiler,
lint_store,
hir_forest.steal(),
hir_forest,
resolver_outputs.steal(),
outputs,
&crate_name))
&crate_name,
&self.gcx,
&self.all_arenas,
&self.arena,
))
})
}
pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
self.queries.ongoing_codegen.compute(|| {
pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> {
self.ongoing_codegen.compute(|| {
let outputs = self.prepare_outputs()?;
self.global_ctxt()?.peek_mut().enter(|tcx| {
tcx.analysis(LOCAL_CRATE).ok();
@ -259,22 +290,58 @@ impl Compiler {
})
}
pub fn link(&self) -> Result<&Query<()>> {
self.queries.link.compute(|| {
let sess = self.session();
pub fn linker(&'tcx self) -> Result<Linker> {
let dep_graph = self.dep_graph()?;
let prepare_outputs = self.prepare_outputs()?;
let ongoing_codegen = self.ongoing_codegen()?;
let ongoing_codegen = self.ongoing_codegen()?.take();
let sess = self.session().clone();
let codegen_backend = self.codegen_backend().clone();
self.codegen_backend().join_codegen_and_link(
ongoing_codegen,
sess,
&*self.dep_graph()?.peek(),
&*self.prepare_outputs()?.peek(),
).map_err(|_| ErrorReported)?;
Ok(())
Ok(Linker {
sess,
dep_graph: dep_graph.peek().clone(),
prepare_outputs: prepare_outputs.take(),
ongoing_codegen: ongoing_codegen.take(),
codegen_backend,
})
}
}
pub struct Linker {
sess: Lrc<Session>,
dep_graph: DepGraph,
prepare_outputs: OutputFilenames,
ongoing_codegen: Box<dyn Any>,
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
}
impl Linker {
pub fn link(self) -> Result<()> {
self.codegen_backend.join_codegen_and_link(
self.ongoing_codegen,
&self.sess,
&self.dep_graph,
&self.prepare_outputs,
).map_err(|_| ErrorReported)
}
}
impl Compiler {
pub fn enter<F, T>(&self, f: F) -> T
where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T
{
let queries = Queries::new(&self);
let ret = f(&queries);
if self.session().opts.debugging_opts.query_stats {
if let Ok(gcx) = queries.global_ctxt() {
gcx.peek().print_stats();
}
}
ret
}
// This method is different to all the other methods in `Compiler` because
// it lacks a `Queries` entry. It's also not currently used. It does serve
@ -282,24 +349,30 @@ impl Compiler {
// between some passes. And see `rustc_driver::run_compiler` for a more
// complex example.
pub fn compile(&self) -> Result<()> {
self.prepare_outputs()?;
let linker = self.enter(|queries| {
queries.prepare_outputs()?;
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
&& self.session().opts.output_types.len() == 1
{
return Ok(())
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
&& self.session().opts.output_types.len() == 1
{
return Ok(None)
}
queries.global_ctxt()?;
// Drop AST after creating GlobalCtxt to free memory.
mem::drop(queries.expansion()?.take());
queries.ongoing_codegen()?;
let linker = queries.linker()?;
Ok(Some(linker))
})?;
if let Some(linker) = linker {
linker.link()?
}
self.global_ctxt()?;
// Drop AST after creating GlobalCtxt to free memory.
mem::drop(self.expansion()?.take());
self.ongoing_codegen()?;
// Drop GlobalCtxt after starting codegen to free memory.
mem::drop(self.global_ctxt()?.take());
self.link().map(|_| ())
Ok(())
}
}

View File

@ -343,14 +343,14 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
registry: rustc_driver::diagnostics_registry(),
};
interface::run_compiler_in_existing_thread_pool(config, |compiler| {
interface::run_compiler_in_existing_thread_pool(config, |compiler| compiler.enter(|queries| {
let sess = compiler.session();
// We need to hold on to the complete resolver, so we cause everything to be
// cloned for the analysis passes to use. Suboptimal, but necessary in the
// current architecture.
let resolver = {
let parts = abort_on_err(compiler.expansion(), sess).peek();
let parts = abort_on_err(queries.expansion(), sess).peek();
let resolver = parts.1.borrow();
// Before we actually clone it, let's force all the extern'd crates to
@ -358,10 +358,11 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
// intra-doc-links
resolver.borrow_mut().access(|resolver| {
for extern_name in &extern_names {
resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID)
.unwrap_or_else(
|()| panic!("Unable to resolve external crate {}", extern_name)
);
resolver.resolve_str_path_error(
DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID
).unwrap_or_else(
|()| panic!("Unable to resolve external crate {}", extern_name)
);
}
});
@ -373,7 +374,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
sess.fatal("Compilation failed, aborting rustdoc");
}
let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take();
let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
global_ctxt.enter(|tcx| {
tcx.analysis(LOCAL_CRATE).ok();
@ -447,8 +448,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
},
sym::plugins => {
report_deprecated_attr("plugins = \"...\"", diag);
eprintln!("WARNING: `#![doc(plugins = \"...\")]` no longer functions; \
see CVE-2018-1000622");
eprintln!("WARNING: `#![doc(plugins = \"...\")]` \
no longer functions; see CVE-2018-1000622");
continue
},
_ => continue,
@ -486,7 +487,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
(krate, ctxt.renderinfo.into_inner(), render_options)
})
})
}))
}
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter

View File

@ -85,14 +85,14 @@ pub fn run(options: Options) -> i32 {
let mut test_args = options.test_args.clone();
let display_warnings = options.display_warnings;
let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> {
let lower_to_hir = compiler.lower_to_hir()?;
let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| {
let lower_to_hir = queries.lower_to_hir()?;
let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate());
let mut opts = scrape_test_config(lower_to_hir.peek().0.krate());
opts.display_warnings |= options.display_warnings;
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
compiler.crate_name()?.peek().to_string(),
queries.crate_name()?.peek().to_string(),
options,
false,
opts,
@ -101,7 +101,8 @@ pub fn run(options: Options) -> i32 {
enable_per_target_ignores,
);
let mut global_ctxt = compiler.global_ctxt()?.take();
let mut global_ctxt = queries.global_ctxt()?.take();
global_ctxt.enter(|tcx| {
let krate = tcx.hir().krate();
let mut hir_collector = HirCollector {
@ -116,8 +117,9 @@ pub fn run(options: Options) -> i32 {
});
});
Ok(collector.tests)
}).expect("compiler aborted in rustdoc!");
let ret : Result<_, ErrorReported> = Ok(collector.tests);
ret
})).expect("compiler aborted in rustdoc!");
test_args.insert(0, "rustdoctest".to_string());

View File

@ -66,6 +66,11 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
interface::run_compiler(config, |compiler| {
// This runs all the passes prior to linking, too.
compiler.link().ok();
let linker = compiler.enter(|queries| {
queries.linker()
});
if let Ok(linker) = linker {
linker.link();
}
});
}