summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_interface
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_interface')
-rw-r--r--compiler/rustc_interface/Cargo.toml4
-rw-r--r--compiler/rustc_interface/src/errors.rs58
-rw-r--r--compiler/rustc_interface/src/interface.rs109
-rw-r--r--compiler/rustc_interface/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/passes.rs23
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs5
-rw-r--r--compiler/rustc_interface/src/queries.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs43
-rw-r--r--compiler/rustc_interface/src/util.rs122
9 files changed, 174 insertions, 195 deletions
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index da4002d09..6a4c5b4d3 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
libloading = "0.7.1"
@@ -38,7 +37,8 @@ rustc_mir_build = { path = "../rustc_mir_build" }
rustc_mir_transform = { path = "../rustc_mir_transform" }
rustc_monomorphize = { path = "../rustc_monomorphize" }
rustc_passes = { path = "../rustc_passes" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+rustc_hir_typeck = { path = "../rustc_hir_typeck" }
rustc_lint = { path = "../rustc_lint" }
rustc_errors = { path = "../rustc_errors" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index 6a497aed4..f5135c78d 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -1,11 +1,11 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use std::io;
use std::path::Path;
-#[derive(SessionDiagnostic)]
-#[diag(interface::ferris_identifier)]
+#[derive(Diagnostic)]
+#[diag(interface_ferris_identifier)]
pub struct FerrisIdentifier {
#[primary_span]
pub spans: Vec<Span>,
@@ -13,76 +13,76 @@ pub struct FerrisIdentifier {
pub first_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::emoji_identifier)]
+#[derive(Diagnostic)]
+#[diag(interface_emoji_identifier)]
pub struct EmojiIdentifier {
#[primary_span]
pub spans: Vec<Span>,
pub ident: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::mixed_bin_crate)]
+#[derive(Diagnostic)]
+#[diag(interface_mixed_bin_crate)]
pub struct MixedBinCrate;
-#[derive(SessionDiagnostic)]
-#[diag(interface::mixed_proc_macro_crate)]
+#[derive(Diagnostic)]
+#[diag(interface_mixed_proc_macro_crate)]
pub struct MixedProcMacroCrate;
-#[derive(SessionDiagnostic)]
-#[diag(interface::proc_macro_doc_without_arg)]
+#[derive(Diagnostic)]
+#[diag(interface_proc_macro_doc_without_arg)]
pub struct ProcMacroDocWithoutArg;
-#[derive(SessionDiagnostic)]
-#[diag(interface::error_writing_dependencies)]
+#[derive(Diagnostic)]
+#[diag(interface_error_writing_dependencies)]
pub struct ErrorWritingDependencies<'a> {
pub path: &'a Path,
pub error: io::Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::input_file_would_be_overwritten)]
+#[derive(Diagnostic)]
+#[diag(interface_input_file_would_be_overwritten)]
pub struct InputFileWouldBeOverWritten<'a> {
pub path: &'a Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::generated_file_conflicts_with_directory)]
+#[derive(Diagnostic)]
+#[diag(interface_generated_file_conflicts_with_directory)]
pub struct GeneratedFileConflictsWithDirectory<'a> {
pub input_path: &'a Path,
pub dir_path: &'a Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::temps_dir_error)]
+#[derive(Diagnostic)]
+#[diag(interface_temps_dir_error)]
pub struct TempsDirError;
-#[derive(SessionDiagnostic)]
-#[diag(interface::out_dir_error)]
+#[derive(Diagnostic)]
+#[diag(interface_out_dir_error)]
pub struct OutDirError;
-#[derive(SessionDiagnostic)]
-#[diag(interface::cant_emit_mir)]
+#[derive(Diagnostic)]
+#[diag(interface_cant_emit_mir)]
pub struct CantEmitMIR {
pub error: io::Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::rustc_error_fatal)]
+#[derive(Diagnostic)]
+#[diag(interface_rustc_error_fatal)]
pub struct RustcErrorFatal {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::rustc_error_unexpected_annotation)]
+#[derive(Diagnostic)]
+#[diag(interface_rustc_error_unexpected_annotation)]
pub struct RustcErrorUnexpectedAnnotation {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::failed_writing_file)]
+#[derive(Diagnostic)]
+#[diag(interface_failed_writing_file)]
pub struct FailedWritingFile<'a> {
pub path: &'a Path,
pub error: io::Error,
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 949bd02ad..89aaa0b95 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -17,7 +17,7 @@ use rustc_session::config::{self, CheckCfg, ErrorOutputType, Input, OutputFilena
use rustc_session::early_error;
use rustc_session::lint;
use rustc_session::parse::{CrateConfig, ParseSess};
-use rustc_session::{DiagnosticOutput, Session};
+use rustc_session::Session;
use rustc_span::source_map::{FileLoader, FileName};
use rustc_span::symbol::sym;
use std::path::PathBuf;
@@ -25,7 +25,10 @@ use std::result;
pub type Result<T> = result::Result<T, ErrorGuaranteed>;
-/// Represents a compiler session.
+/// Represents a compiler session. Note that every `Compiler` contains a
+/// `Session`, but `Compiler` also contains some things that cannot be in
+/// `Session`, due to `Session` being in a crate that has many fewer
+/// dependencies than this crate.
///
/// Can be used to run `rustc_interface` queries.
/// Created by passing [`Config`] to [`run_compiler`].
@@ -247,7 +250,6 @@ pub struct Config {
pub output_dir: Option<PathBuf>,
pub output_file: Option<PathBuf>,
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- pub diagnostic_output: DiagnosticOutput,
pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -276,59 +278,6 @@ pub struct Config {
pub registry: Registry,
}
-pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R) -> R {
- crate::callbacks::setup_callbacks();
-
- let registry = &config.registry;
- let (mut sess, codegen_backend) = util::create_session(
- config.opts,
- config.crate_cfg,
- config.crate_check_cfg,
- config.diagnostic_output,
- config.file_loader,
- config.input_path.clone(),
- config.lint_caps,
- config.make_codegen_backend,
- registry.clone(),
- );
-
- if let Some(parse_sess_created) = config.parse_sess_created {
- parse_sess_created(
- &mut Lrc::get_mut(&mut sess)
- .expect("create_session() should never share the returned session")
- .parse_sess,
- );
- }
-
- let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
-
- let compiler = Compiler {
- sess,
- codegen_backend,
- input: config.input,
- input_path: config.input_path,
- output_dir: config.output_dir,
- output_file: config.output_file,
- temps_dir,
- register_lints: config.register_lints,
- override_queries: config.override_queries,
- };
-
- rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
- let r = {
- let _sess_abort_error = OnDrop(|| {
- compiler.sess.finish_diagnostics(registry);
- });
-
- f(&compiler)
- };
-
- let prof = compiler.sess.prof.clone();
- prof.generic_activity("drop_compiler").run(move || drop(compiler));
- r
- })
-}
-
// JUSTIFICATION: before session exists, only config
#[allow(rustc::bad_opt_access)]
pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
@@ -336,7 +285,53 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
util::run_in_thread_pool_with_globals(
config.opts.edition,
config.opts.unstable_opts.threads,
- || create_compiler_and_run(config, f),
+ || {
+ crate::callbacks::setup_callbacks();
+
+ let registry = &config.registry;
+ let (mut sess, codegen_backend) = util::create_session(
+ config.opts,
+ config.crate_cfg,
+ config.crate_check_cfg,
+ config.file_loader,
+ config.input_path.clone(),
+ config.lint_caps,
+ config.make_codegen_backend,
+ registry.clone(),
+ );
+
+ if let Some(parse_sess_created) = config.parse_sess_created {
+ parse_sess_created(&mut sess.parse_sess);
+ }
+
+ let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
+
+ let compiler = Compiler {
+ sess: Lrc::new(sess),
+ codegen_backend: Lrc::new(codegen_backend),
+ input: config.input,
+ input_path: config.input_path,
+ output_dir: config.output_dir,
+ output_file: config.output_file,
+ temps_dir,
+ register_lints: config.register_lints,
+ override_queries: config.override_queries,
+ };
+
+ rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
+ let r = {
+ let _sess_abort_error = OnDrop(|| {
+ compiler.sess.finish_diagnostics(registry);
+ });
+
+ f(&compiler)
+ };
+
+ let prof = compiler.sess.prof.clone();
+ prof.generic_activity("drop_compiler").run(move || drop(compiler));
+ r
+ })
+ },
)
}
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 41cd7b0e9..a41a749ee 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,5 +1,4 @@
#![feature(box_patterns)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(internal_output_capture)]
#![feature(thread_spawn_unchecked)]
#![feature(once_cell)]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index c41b154c3..7f1d21bf1 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::{ErrorGuaranteed, PResult};
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
use rustc_hir::def_id::StableCrateId;
-use rustc_hir::definitions::Definitions;
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
@@ -30,14 +29,13 @@ use rustc_plugin_impl as plugin;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
-use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn};
+use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn};
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::FileName;
use rustc_trait_selection::traits;
-use rustc_typeck as typeck;
use std::any::Any;
use std::cell::RefCell;
@@ -136,10 +134,7 @@ mod boxed_resolver {
f((&mut *resolver).as_mut().unwrap())
}
- pub fn to_resolver_outputs(
- resolver: Rc<RefCell<BoxedResolver>>,
- ) -> (Definitions, Box<CrateStoreDyn>, ty::ResolverOutputs, ty::ResolverAstLowering)
- {
+ pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs {
match Rc::try_unwrap(resolver) {
Ok(resolver) => {
let mut resolver = resolver.into_inner();
@@ -736,11 +731,11 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
rustc_mir_transform::provide(providers);
rustc_monomorphize::provide(providers);
rustc_privacy::provide(providers);
- typeck::provide(providers);
+ rustc_hir_analysis::provide(providers);
+ rustc_hir_typeck::provide(providers);
ty::provide(providers);
traits::provide(providers);
rustc_passes::provide(providers);
- rustc_resolve::provide(providers);
rustc_traits::provide(providers);
rustc_ty_utils::provide(providers);
rustc_metadata::provide(providers);
@@ -789,8 +784,7 @@ pub fn create_global_ctxt<'tcx>(
// incr. comp. yet.
dep_graph.assert_ignored();
- let (definitions, cstore, resolver_outputs, resolver_for_lowering) =
- BoxedResolver::to_resolver_outputs(resolver);
+ let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver);
let sess = &compiler.session();
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
@@ -817,10 +811,7 @@ pub fn create_global_ctxt<'tcx>(
lint_store,
arena,
hir_arena,
- definitions,
- cstore,
resolver_outputs,
- resolver_for_lowering,
krate,
dep_graph,
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
@@ -880,7 +871,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
});
// passes are timed inside typeck
- typeck::check_crate(tcx)?;
+ rustc_hir_analysis::check_crate(tcx)?;
sess.time("misc_checking_2", || {
parallel!(
@@ -936,7 +927,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
sess.time("misc_checking_3", || {
parallel!(
{
- tcx.ensure().privacy_access_levels(());
+ tcx.ensure().effective_visibilities(());
parallel!(
{
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 5371c513d..4c236c693 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -1,4 +1,3 @@
-use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
@@ -10,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
for id in tcx.hir().items() {
let attrs = finder.tcx.hir().attrs(id.hir_id());
if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
- finder.decls = Some(id.def_id);
+ finder.decls = Some(id.owner_id.def_id);
}
}
@@ -19,7 +18,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
struct Finder<'tcx> {
tcx: TyCtxt<'tcx>,
- decls: Option<hir::def_id::LocalDefId>,
+ decls: Option<LocalDefId>,
}
pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 6c725a01b..91d180e1e 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -246,6 +246,10 @@ impl<'tcx> Queries<'tcx> {
// Don't do code generation if there were any errors
self.session().compile_status()?;
+ // If we have any delayed bugs, for example because we created TyKind::Error earlier,
+ // it's likely that codegen will only cause more ICEs, obscuring the original problem
+ self.session().diagnostic().flush_delayed();
+
// Hook for UI tests.
Self::check_for_rustc_errors_attr(tcx);
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index c7615a577..eb8e65a6d 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -17,7 +17,7 @@ use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, Switc
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use rustc_session::{build_session, getopts, DiagnosticOutput, Session};
+use rustc_session::{build_session, getopts, Session};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm;
@@ -40,16 +40,7 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options
fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
let registry = registry::Registry::new(&[]);
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
- let sess = build_session(
- sessopts,
- None,
- None,
- registry,
- DiagnosticOutput::Default,
- Default::default(),
- None,
- None,
- );
+ let sess = build_session(sessopts, None, None, registry, Default::default(), None, None);
(sess, cfg)
}
@@ -540,7 +531,7 @@ fn test_codegen_options_tracking_hash() {
}
// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
untracked!(ar, String::from("abc"));
untracked!(codegen_units, Some(42));
untracked!(default_linker_libraries, true);
@@ -556,6 +547,7 @@ fn test_codegen_options_tracking_hash() {
untracked!(rpath, true);
untracked!(save_temps, true);
untracked!(strip, Strip::Debuginfo);
+ // tidy-alphabetical-end
macro_rules! tracked {
($name: ident, $non_default_value: expr) => {
@@ -567,7 +559,7 @@ fn test_codegen_options_tracking_hash() {
}
// Make sure that changing a [TRACKED] option changes the hash.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
tracked!(code_model, Some(CodeModel::Large));
tracked!(control_flow_guard, CFGuard::Checks);
tracked!(debug_assertions, Some(true));
@@ -577,8 +569,8 @@ fn test_codegen_options_tracking_hash() {
tracked!(force_unwind_tables, Some(true));
tracked!(inline_threshold, Some(0xf007ba11));
tracked!(instrument_coverage, Some(InstrumentCoverage::All));
- tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
tracked!(link_dead_code, Some(true));
+ tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
tracked!(llvm_args, vec![String::from("1"), String::from("2")]);
tracked!(lto, LtoCli::Fat);
tracked!(metadata, vec![String::from("A"), String::from("B")]);
@@ -599,6 +591,7 @@ fn test_codegen_options_tracking_hash() {
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
tracked!(target_cpu, Some(String::from("abc")));
tracked!(target_feature, String::from("all the features, all of them"));
+ // tidy-alphabetical-end
}
#[test]
@@ -619,12 +612,13 @@ fn test_top_level_options_tracked_no_crate() {
}
// Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash.
- // This list is in alphabetical order.
- tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
+ // tidy-alphabetical-start
tracked!(
real_rust_source_base_dir,
Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into())
);
+ tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
+ // tidy-alphabetical-end
}
#[test]
@@ -641,7 +635,7 @@ fn test_unstable_options_tracking_hash() {
}
// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
untracked!(assert_incr_state, Some(String::from("loaded")));
untracked!(deduplicate_diagnostics, false);
untracked!(dep_tasks, true);
@@ -654,6 +648,7 @@ fn test_unstable_options_tracking_hash() {
untracked!(dump_mir_dir, String::from("abc"));
untracked!(dump_mir_exclude_pass_number, true);
untracked!(dump_mir_graphviz, true);
+ untracked!(dylib_lto, true);
untracked!(emit_stack_sizes, true);
untracked!(future_incompat_test, true);
untracked!(hir_stats, true);
@@ -678,12 +673,12 @@ fn test_unstable_options_tracking_hash() {
untracked!(perf_stats, true);
// `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
- untracked!(profile_closures, true);
untracked!(print_llvm_passes, true);
untracked!(print_mono_items, Some(String::from("abc")));
untracked!(print_type_sizes, true);
untracked!(proc_macro_backtrace, true);
untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread);
+ untracked!(profile_closures, true);
untracked!(query_dep_graph, true);
untracked!(save_analysis, true);
untracked!(self_profile, SwitchWithOptPath::Enabled(None));
@@ -692,7 +687,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(span_free_formats, true);
untracked!(temps_dir, Some(String::from("abc")));
untracked!(threads, 99);
- untracked!(time, true);
untracked!(time_llvm_passes, true);
untracked!(time_passes, true);
untracked!(trace_macros, true);
@@ -702,6 +696,7 @@ fn test_unstable_options_tracking_hash() {
untracked!(unstable_options, true);
untracked!(validate_mir, true);
untracked!(verbose, true);
+ // tidy-alphabetical-end
macro_rules! tracked {
($name: ident, $non_default_value: expr) => {
@@ -713,7 +708,7 @@ fn test_unstable_options_tracking_hash() {
}
// Make sure that changing a [TRACKED] option changes the hash.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
tracked!(allow_features, Some(vec![String::from("lang_items")]));
tracked!(always_encode_mir, true);
tracked!(asm_comments, true);
@@ -734,10 +729,10 @@ fn test_unstable_options_tracking_hash() {
tracked!(debug_macros, true);
tracked!(dep_info_omit_d_target, true);
tracked!(drop_tracking, true);
- tracked!(export_executable_symbols, true);
tracked!(dual_proc_macros, true);
tracked!(dwarf_version, Some(5));
tracked!(emit_thin_lto, false);
+ tracked!(export_executable_symbols, true);
tracked!(fewer_names, Some(true));
tracked!(force_unstable_if_unmarked, true);
tracked!(fuel, Some(("abc".to_string(), 99)));
@@ -758,11 +753,10 @@ fn test_unstable_options_tracking_hash() {
tracked!(mir_opt_level, Some(4));
tracked!(move_size_limit, Some(4096));
tracked!(mutable_noalias, Some(true));
- tracked!(new_llvm_pass_manager, Some(true));
tracked!(no_generate_arange_section, true);
tracked!(no_link, true);
- tracked!(no_unique_section_names, true);
tracked!(no_profiler_runtime, true);
+ tracked!(no_unique_section_names, true);
tracked!(oom, OomStrategy::Panic);
tracked!(osx_rpath_install_name, true);
tracked!(packed_bundled_libs, true);
@@ -775,8 +769,8 @@ fn test_unstable_options_tracking_hash() {
tracked!(print_fuel, Some("abc".to_string()));
tracked!(profile, true);
tracked!(profile_emit, Some(PathBuf::from("abc")));
- tracked!(profiler_runtime, "abc".to_string());
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
+ tracked!(profiler_runtime, "abc".to_string());
tracked!(relax_elf_relocations, Some(true));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
@@ -805,6 +799,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(verify_llvm_ir, true);
tracked!(virtual_function_elimination, true);
tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
+ // tidy-alphabetical-end
macro_rules! tracked_no_crate_hash {
($name: ident, $non_default_value: expr) => {
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index f7e70d355..519b8a7fc 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -3,22 +3,15 @@ use libloading::Library;
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-#[cfg(parallel_compiler)]
-use rustc_data_structures::jobserver;
-use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry;
-#[cfg(parallel_compiler)]
-use rustc_middle::ty::tls;
use rustc_parse::validate_attr;
-#[cfg(parallel_compiler)]
-use rustc_query_impl::{QueryContext, QueryCtxt};
use rustc_session as session;
use rustc_session::config::CheckCfg;
use rustc_session::config::{self, CrateType};
use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::CrateConfig;
-use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
+use rustc_session::{early_error, filesearch, output, Session};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::FileLoader;
@@ -26,8 +19,6 @@ use rustc_span::symbol::{sym, Symbol};
use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::mem;
-#[cfg(not(parallel_compiler))]
-use std::panic;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::OnceLock;
@@ -65,7 +56,6 @@ pub fn create_session(
sopts: config::Options,
cfg: FxHashSet<(String, Option<String>)>,
check_cfg: CheckCfg,
- diagnostic_output: DiagnosticOutput,
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
input_path: Option<PathBuf>,
lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -73,7 +63,7 @@ pub fn create_session(
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
descriptions: Registry,
-) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
+) -> (Session, Box<dyn CodegenBackend>) {
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
make_codegen_backend(&sopts)
} else {
@@ -104,7 +94,6 @@ pub fn create_session(
input_path,
bundle,
descriptions,
- diagnostic_output,
lint_caps,
file_loader,
target_override,
@@ -121,7 +110,7 @@ pub fn create_session(
sess.parse_sess.config = cfg;
sess.parse_sess.check_config = check_cfg;
- (Lrc::new(sess), Lrc::new(codegen_backend))
+ (sess, codegen_backend)
}
const STACK_SIZE: usize = 8 * 1024 * 1024;
@@ -132,79 +121,86 @@ fn get_stack_size() -> Option<usize> {
env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
}
-/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
-/// for `'static` bounds.
-#[cfg(not(parallel_compiler))]
-fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
- // SAFETY: join() is called immediately, so any closure captures are still
- // alive.
- match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() {
- Ok(v) => v,
- Err(e) => panic::resume_unwind(e),
- }
-}
-
#[cfg(not(parallel_compiler))]
-pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
_threads: usize,
f: F,
) -> R {
- let mut cfg = thread::Builder::new().name("rustc".to_string());
-
+ // The "thread pool" is a single spawned thread in the non-parallel
+ // compiler. We run on a spawned thread instead of the main thread (a) to
+ // provide control over the stack size, and (b) to increase similarity with
+ // the parallel compiler, in particular to ensure there is no accidental
+ // sharing of data between the main thread and the compilation thread
+ // (which might cause problems for the parallel compiler).
+ let mut builder = thread::Builder::new().name("rustc".to_string());
if let Some(size) = get_stack_size() {
- cfg = cfg.stack_size(size);
+ builder = builder.stack_size(size);
}
- let main_handler = move || rustc_span::create_session_globals_then(edition, f);
-
- scoped_thread(cfg, main_handler)
-}
-
-/// Creates a new thread and forwards information in thread locals to it.
-/// The new thread runs the deadlock handler.
-/// Must only be called when a deadlock is about to happen.
-#[cfg(parallel_compiler)]
-unsafe fn handle_deadlock() {
- let registry = rustc_rayon_core::Registry::current();
-
- let query_map = tls::with(|tcx| {
- QueryCtxt::from_tcx(tcx)
- .try_collect_active_jobs()
- .expect("active jobs shouldn't be locked in deadlock handler")
- });
- thread::spawn(move || rustc_query_impl::deadlock(query_map, &registry));
+ // We build the session globals and run `f` on the spawned thread, because
+ // `SessionGlobals` does not impl `Send` in the non-parallel compiler.
+ thread::scope(|s| {
+ // `unwrap` is ok here because `spawn_scoped` only panics if the thread
+ // name contains null bytes.
+ let r = builder
+ .spawn_scoped(s, move || rustc_span::create_session_globals_then(edition, f))
+ .unwrap()
+ .join();
+
+ match r {
+ Ok(v) => v,
+ Err(e) => std::panic::resume_unwind(e),
+ }
+ })
}
#[cfg(parallel_compiler)]
-pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
threads: usize,
f: F,
) -> R {
- let mut config = rayon::ThreadPoolBuilder::new()
+ use rustc_data_structures::jobserver;
+ use rustc_middle::ty::tls;
+ use rustc_query_impl::{deadlock, QueryContext, QueryCtxt};
+
+ let mut builder = rayon::ThreadPoolBuilder::new()
.thread_name(|_| "rustc".to_string())
.acquire_thread_handler(jobserver::acquire_thread)
.release_thread_handler(jobserver::release_thread)
.num_threads(threads)
- .deadlock_handler(|| unsafe { handle_deadlock() });
-
+ .deadlock_handler(|| {
+ // On deadlock, creates a new thread and forwards information in thread
+ // locals to it. The new thread runs the deadlock handler.
+ let query_map = tls::with(|tcx| {
+ QueryCtxt::from_tcx(tcx)
+ .try_collect_active_jobs()
+ .expect("active jobs shouldn't be locked in deadlock handler")
+ });
+ let registry = rustc_rayon_core::Registry::current();
+ thread::spawn(move || deadlock(query_map, &registry));
+ });
if let Some(size) = get_stack_size() {
- config = config.stack_size(size);
+ builder = builder.stack_size(size);
}
- let with_pool = move |pool: &rayon::ThreadPool| pool.install(f);
-
+ // We create the session globals on the main thread, then create the thread
+ // pool. Upon creation, each worker thread created gets a copy of the
+ // session globals in TLS. This is possible because `SessionGlobals` impls
+ // `Send` in the parallel compiler.
rustc_span::create_session_globals_then(edition, || {
rustc_span::with_session_globals(|session_globals| {
- // The main handler runs for each Rayon worker thread and sets up
- // the thread local rustc uses. `session_globals` is captured and set
- // on the new threads.
- let main_handler = move |thread: rayon::ThreadBuilder| {
- rustc_span::set_session_globals_then(session_globals, || thread.run())
- };
-
- config.build_scoped(main_handler, with_pool).unwrap()
+ builder
+ .build_scoped(
+ // Initialize each new worker thread when created.
+ move |thread: rayon::ThreadBuilder| {
+ rustc_span::set_session_globals_then(session_globals, || thread.run())
+ },
+ // Run `f` on the first thread in the thread pool.
+ move |pool: &rayon::ThreadPool| pool.install(f),
+ )
+ .unwrap()
})
})
}