summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_interface/src/passes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_interface/src/passes.rs')
-rw-r--r--compiler/rustc_interface/src/passes.rs308
1 files changed, 106 insertions, 202 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 379a76528..81c1d665e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1,9 +1,4 @@
-use crate::errors::{
- CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier,
- GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate,
- MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg,
- TempsDirError,
-};
+use crate::errors;
use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;
@@ -13,11 +8,12 @@ use rustc_ast::{self as ast, visit};
use rustc_borrowck as mir_borrowck;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
+use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
-use rustc_errors::{ErrorGuaranteed, PResult};
+use rustc_errors::PResult;
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
-use rustc_hir::def_id::StableCrateId;
-use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
+use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
+use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
@@ -28,9 +24,9 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_a
use rustc_passes::{self, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
-use rustc_resolve::{Resolver, ResolverArenas};
+use rustc_resolve::Resolver;
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
-use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn, Untracked};
+use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, Untracked};
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
@@ -40,14 +36,10 @@ use rustc_target::spec::PanicStrategy;
use rustc_trait_selection::traits;
use std::any::Any;
-use std::cell::RefCell;
use std::ffi::OsString;
use std::io::{self, BufWriter, Write};
-use std::marker::PhantomPinned;
use std::path::{Path, PathBuf};
-use std::pin::Pin;
-use std::rc::Rc;
-use std::sync::LazyLock;
+use std::sync::{Arc, LazyLock};
use std::{env, fs, iter};
pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
@@ -80,93 +72,6 @@ fn count_nodes(krate: &ast::Crate) -> usize {
counter.count
}
-pub use boxed_resolver::BoxedResolver;
-mod boxed_resolver {
- use super::*;
-
- pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);
-
- struct BoxedResolverInner {
- session: Lrc<Session>,
- resolver_arenas: Option<ResolverArenas<'static>>,
- resolver: Option<Resolver<'static>>,
- _pin: PhantomPinned,
- }
-
- // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
- // then resolver_arenas and session.
- impl Drop for BoxedResolverInner {
- fn drop(&mut self) {
- self.resolver.take();
- self.resolver_arenas.take();
- }
- }
-
- impl BoxedResolver {
- pub(super) fn new(
- session: Lrc<Session>,
- make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>,
- ) -> BoxedResolver {
- let mut boxed_resolver = Box::new(BoxedResolverInner {
- session,
- resolver_arenas: Some(Resolver::arenas()),
- resolver: None,
- _pin: PhantomPinned,
- });
- // SAFETY: `make_resolver` takes a resolver arena with an arbitrary lifetime and
- // returns a resolver with the same lifetime as the arena. We ensure that the arena
- // outlives the resolver in the drop impl and elsewhere so these transmutes are sound.
- unsafe {
- let resolver = make_resolver(
- std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
- std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
- boxed_resolver.resolver_arenas.as_ref().unwrap(),
- ),
- );
- boxed_resolver.resolver = Some(resolver);
- BoxedResolver(Pin::new_unchecked(boxed_resolver))
- }
- }
-
- pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
- // SAFETY: The resolver doesn't need to be pinned.
- let mut resolver = unsafe {
- self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
- };
- f((&mut *resolver).as_mut().unwrap())
- }
-
- pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs {
- match Rc::try_unwrap(resolver) {
- Ok(resolver) => {
- let mut resolver = resolver.into_inner();
- // SAFETY: The resolver doesn't need to be pinned.
- let mut resolver = unsafe {
- resolver
- .0
- .as_mut()
- .map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
- };
- resolver.take().unwrap().into_outputs()
- }
- Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
- }
- }
- }
-}
-
-pub fn create_resolver(
- sess: Lrc<Session>,
- metadata_loader: Box<MetadataLoaderDyn>,
- krate: &ast::Crate,
- crate_name: Symbol,
-) -> BoxedResolver {
- trace!("create_resolver");
- BoxedResolver::new(sess, move |sess, resolver_arenas| {
- Resolver::new(sess, krate, crate_name, metadata_loader, resolver_arenas)
- })
-}
-
pub fn register_plugins<'a>(
sess: &'a Session,
metadata_loader: &'a dyn MetadataLoader,
@@ -267,14 +172,12 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
/// harness if one is to be provided, injection of a dependency on the
/// standard library and prelude, and name resolution.
-pub fn configure_and_expand(
- sess: &Session,
- lint_store: &LintStore,
- mut krate: ast::Crate,
- crate_name: Symbol,
- resolver: &mut Resolver<'_>,
-) -> Result<ast::Crate> {
- trace!("configure_and_expand");
+#[instrument(level = "trace", skip(krate, resolver))]
+fn configure_and_expand(mut krate: ast::Crate, 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, resolver.registered_tools(), &krate, crate_name);
rustc_builtin_macros::register_builtin_macros(resolver);
@@ -345,20 +248,19 @@ pub fn configure_and_expand(
ecx.check_unused_macros();
});
- let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
+ // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
+ // with a large AST
+ if ecx.reduced_recursion_limit.is_some() {
+ sess.abort_if_errors();
+ unreachable!();
+ }
if cfg!(windows) {
env::set_var("PATH", &old_path);
}
- if recursion_limit_hit {
- // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
- // with a large AST
- Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
- } else {
- Ok(krate)
- }
- })?;
+ krate
+ });
sess.time("maybe_building_test_harness", || {
rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate)
@@ -374,39 +276,29 @@ pub fn configure_and_expand(
if crate_types.len() > 1 {
if is_executable_crate {
- sess.emit_err(MixedBinCrate);
+ sess.emit_err(errors::MixedBinCrate);
}
if is_proc_macro_crate {
- sess.emit_err(MixedProcMacroCrate);
+ sess.emit_err(errors::MixedProcMacroCrate);
}
}
if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
- sess.emit_warning(ProcMacroCratePanicAbort);
+ sess.emit_warning(errors::ProcMacroCratePanicAbort);
}
- // For backwards compatibility, we don't try to run proc macro injection
- // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being
- // specified. This should only affect users who manually invoke 'rustdoc', as
- // 'cargo doc' will automatically pass the proper '--crate-type' flags.
- // However, we do emit a warning, to let such users know that they should
- // start passing '--crate-type proc-macro'
- if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate {
- sess.emit_warning(ProcMacroDocWithoutArg);
- } else {
- krate = sess.time("maybe_create_a_macro_crate", || {
- let is_test_crate = sess.opts.test;
- rustc_builtin_macros::proc_macro_harness::inject(
- sess,
- resolver,
- krate,
- is_proc_macro_crate,
- has_proc_macro_decls,
- is_test_crate,
- sess.diagnostic(),
- )
- });
- }
+ krate = sess.time("maybe_create_a_macro_crate", || {
+ let is_test_crate = sess.opts.test;
+ rustc_builtin_macros::proc_macro_harness::inject(
+ sess,
+ resolver,
+ krate,
+ is_proc_macro_crate,
+ has_proc_macro_decls,
+ is_test_crate,
+ sess.diagnostic(),
+ )
+ });
// Done with macro expansion!
@@ -441,9 +333,9 @@ pub fn configure_and_expand(
spans.sort();
if ident == sym::ferris {
let first_span = spans[0];
- sess.emit_err(FerrisIdentifier { spans, first_span });
+ sess.emit_err(errors::FerrisIdentifier { spans, first_span });
} else {
- sess.emit_err(EmojiIdentifier { spans, ident });
+ sess.emit_err(errors::EmojiIdentifier { spans, ident });
}
}
});
@@ -461,7 +353,7 @@ pub fn configure_and_expand(
)
});
- Ok(krate)
+ krate
}
// Returns all the paths that correspond to generated files.
@@ -548,7 +440,7 @@ fn escape_dep_env(symbol: Symbol) -> String {
fn write_out_deps(
sess: &Session,
- boxed_resolver: &RefCell<BoxedResolver>,
+ cstore: &CrateStoreDyn,
outputs: &OutputFilenames,
out_filenames: &[PathBuf],
) {
@@ -600,20 +492,19 @@ fn write_out_deps(
}
}
- boxed_resolver.borrow_mut().access(|resolver| {
- for cnum in resolver.cstore().crates_untracked() {
- let source = resolver.cstore().crate_source_untracked(cnum);
- if let Some((path, _)) = &source.dylib {
- files.push(escape_dep_filename(&path.display().to_string()));
- }
- if let Some((path, _)) = &source.rlib {
- files.push(escape_dep_filename(&path.display().to_string()));
- }
- if let Some((path, _)) = &source.rmeta {
- files.push(escape_dep_filename(&path.display().to_string()));
- }
+ let cstore = cstore.as_any().downcast_ref::<CStore>().unwrap();
+ for cnum in cstore.crates_untracked() {
+ let source = cstore.crate_source_untracked(cnum);
+ if let Some((path, _)) = &source.dylib {
+ files.push(escape_dep_filename(&path.display().to_string()));
+ }
+ if let Some((path, _)) = &source.rlib {
+ files.push(escape_dep_filename(&path.display().to_string()));
}
- });
+ if let Some((path, _)) = &source.rmeta {
+ files.push(escape_dep_filename(&path.display().to_string()));
+ }
+ }
}
let mut file = BufWriter::new(fs::File::create(&deps_filename)?);
@@ -656,18 +547,38 @@ fn write_out_deps(
}
}
Err(error) => {
- sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error });
+ sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error });
}
}
}
-pub fn prepare_outputs(
- sess: &Session,
- krate: &ast::Crate,
- boxed_resolver: &RefCell<BoxedResolver>,
- crate_name: Symbol,
-) -> Result<OutputFilenames> {
+fn resolver_for_lowering<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ (): (),
+) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+ let arenas = Resolver::arenas();
+ let krate = tcx.crate_for_resolver(()).steal();
+ let mut resolver = Resolver::new(tcx, &krate, &arenas);
+ let krate = configure_and_expand(krate, &mut resolver);
+
+ // Make sure we don't mutate the cstore from here on.
+ tcx.untracked().cstore.leak();
+
+ let ty::ResolverOutputs {
+ global_ctxt: untracked_resolutions,
+ ast_lowering: untracked_resolver_for_lowering,
+ } = resolver.into_outputs();
+
+ let feed = tcx.feed_unit_query();
+ feed.resolutions(tcx.arena.alloc(untracked_resolutions));
+ tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate))))
+}
+
+fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
+ let sess = tcx.sess;
let _timer = sess.timer("prepare_outputs");
+ let (_, krate) = &*tcx.resolver_for_lowering(()).borrow();
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
// FIXME: rustdoc passes &[] instead of &krate.attrs here
let outputs = util::build_output_filenames(&krate.attrs, sess);
@@ -679,25 +590,24 @@ pub fn prepare_outputs(
if let Some(ref input_path) = sess.io.input.opt_path() {
if sess.opts.will_create_output_file() {
if output_contains_path(&output_paths, input_path) {
- let reported = sess.emit_err(InputFileWouldBeOverWritten { path: input_path });
- return Err(reported);
+ sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path });
}
if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) {
- let reported =
- sess.emit_err(GeneratedFileConflictsWithDirectory { input_path, dir_path });
- return Err(reported);
+ sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory {
+ input_path,
+ dir_path,
+ });
}
}
}
if let Some(ref dir) = sess.io.temps_dir {
if fs::create_dir_all(dir).is_err() {
- let reported = sess.emit_err(TempsDirError);
- return Err(reported);
+ sess.emit_fatal(errors::TempsDirError);
}
}
- write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
+ write_out_deps(sess, &*tcx.cstore_untracked(), &outputs, &output_paths);
let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1;
@@ -705,19 +615,20 @@ pub fn prepare_outputs(
if !only_dep_info {
if let Some(ref dir) = sess.io.output_dir {
if fs::create_dir_all(dir).is_err() {
- let reported = sess.emit_err(OutDirError);
- return Err(reported);
+ sess.emit_fatal(errors::OutDirError);
}
}
}
- Ok(outputs)
+ outputs.into()
}
pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
let providers = &mut Providers::default();
providers.analysis = analysis;
providers.hir_crate = rustc_ast_lowering::lower_to_hir;
+ providers.output_filenames = output_filenames;
+ providers.resolver_for_lowering = resolver_for_lowering;
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
rustc_middle::hir::provide(providers);
@@ -747,30 +658,16 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock:
extern_providers
});
-pub struct QueryContext<'tcx> {
- gcx: &'tcx GlobalCtxt<'tcx>,
-}
-
-impl<'tcx> QueryContext<'tcx> {
- pub fn enter<F, R>(&mut self, f: F) -> R
- where
- F: FnOnce(TyCtxt<'tcx>) -> R,
- {
- let icx = ty::tls::ImplicitCtxt::new(self.gcx);
- ty::tls::enter_context(&icx, |_| f(icx.tcx))
- }
-}
-
pub fn create_global_ctxt<'tcx>(
compiler: &'tcx Compiler,
lint_store: Lrc<LintStore>,
dep_graph: DepGraph,
untracked: Untracked,
queries: &'tcx OnceCell<TcxQueries<'tcx>>,
- global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
+ gcx_cell: &'tcx OnceCell<GlobalCtxt<'tcx>>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
-) -> QueryContext<'tcx> {
+) -> &'tcx GlobalCtxt<'tcx> {
// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
// incr. comp. yet.
@@ -794,8 +691,8 @@ pub fn create_global_ctxt<'tcx>(
TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
});
- let gcx = sess.time("setup_global_ctxt", || {
- global_ctxt.get_or_init(move || {
+ sess.time("setup_global_ctxt", || {
+ gcx_cell.get_or_init(move || {
TyCtxt::create_global_ctxt(
sess,
lint_store,
@@ -808,9 +705,7 @@ pub fn create_global_ctxt<'tcx>(
rustc_query_impl::query_callbacks(arena),
)
})
- });
-
- QueryContext { gcx }
+ })
}
/// Runs the resolution, type-checking, region checking and other
@@ -900,6 +795,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
}
});
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ tcx.hir().par_body_owners(|def_id| {
+ if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) {
+ tcx.ensure().mir_generator_witnesses(def_id);
+ tcx.ensure().check_generator_obligations(def_id);
+ }
+ });
+ }
+
sess.time("layout_testing", || layout_test::test_layout(tcx));
// Avoid overwhelming user with errors if borrow checking failed.
@@ -975,7 +879,7 @@ pub fn start_codegen<'tcx>(
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
- tcx.sess.emit_err(CantEmitMIR { error });
+ tcx.sess.emit_err(errors::CantEmitMIR { error });
tcx.sess.abort_if_errors();
}
}