diff options
Diffstat (limited to 'compiler/rustc_interface/src')
-rw-r--r-- | compiler/rustc_interface/src/interface.rs | 318 | ||||
-rw-r--r-- | compiler/rustc_interface/src/lib.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_interface/src/passes.rs | 73 | ||||
-rw-r--r-- | compiler/rustc_interface/src/queries.rs | 168 | ||||
-rw-r--r-- | compiler/rustc_interface/src/tests.rs | 104 | ||||
-rw-r--r-- | compiler/rustc_interface/src/util.rs | 39 |
6 files changed, 308 insertions, 400 deletions
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c4962707f..d58d60fc8 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -1,26 +1,24 @@ use crate::util; use rustc_ast::token; -use rustc_ast::{self as ast, LitKind, MetaItemKind}; +use rustc_ast::{LitKind, MetaItemKind}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::defer; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; -use rustc_errors::{ErrorGuaranteed, Handler}; +use rustc_errors::{DiagCtxt, ErrorGuaranteed}; use rustc_lint::LintStore; +use rustc_middle::ty; use rustc_middle::util::Providers; -use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; -use rustc_session::config::{ - self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames, -}; +use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::parse::ParseSess; -use rustc_session::{lint, CompilerIO, EarlyErrorHandler, Session}; +use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session}; use rustc_span::source_map::FileLoader; use rustc_span::symbol::sym; use rustc_span::FileName; @@ -38,33 +36,13 @@ pub type Result<T> = result::Result<T, ErrorGuaranteed>; /// Can be used to run `rustc_interface` queries. /// Created by passing [`Config`] to [`run_compiler`]. pub struct Compiler { - pub(crate) sess: Lrc<Session>, - codegen_backend: Lrc<dyn CodegenBackend>, - pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>, + pub sess: Session, + pub codegen_backend: Box<dyn CodegenBackend>, pub(crate) override_queries: Option<fn(&Session, &mut Providers)>, } -impl Compiler { - pub fn session(&self) -> &Lrc<Session> { - &self.sess - } - pub fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> { - &self.codegen_backend - } - pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> { - &self.register_lints - } - pub fn build_output_filenames( - &self, - sess: &Session, - attrs: &[ast::Attribute], - ) -> OutputFilenames { - util::build_output_filenames(attrs, sess) - } -} - /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`. -pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg { +pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg { cfgs.into_iter() .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( @@ -74,10 +52,13 @@ pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg { macro_rules! error { ($reason: expr) => { - handler.early_error(format!( + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + dcx.struct_fatal(format!( concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s - )); + )) + .emit(); }; } @@ -119,14 +100,13 @@ pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg { } /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. -pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg { +pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg { // If any --check-cfg is passed then exhaustive_values and exhaustive_names // are enabled by default. let exhaustive_names = !specs.is_empty(); let exhaustive_values = !specs.is_empty(); let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; - let mut old_syntax = None; for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--check-cfg={s}`" @@ -135,10 +115,13 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) - macro_rules! error { ($reason:expr) => { - handler.early_error(format!( + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + dcx.struct_fatal(format!( concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s )) + .emit() }; } @@ -164,162 +147,101 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) - expected_error(); }; - let mut set_old_syntax = || { - // defaults are flipped for the old syntax - if old_syntax == None { - check_cfg.exhaustive_names = false; - check_cfg.exhaustive_values = false; - } - old_syntax = Some(true); - }; - - if meta_item.has_name(sym::names) { - set_old_syntax(); - - check_cfg.exhaustive_names = true; - for arg in args { - if arg.is_word() && let Some(ident) = arg.ident() { - check_cfg.expecteds.entry(ident.name).or_insert(ExpectedValues::Any); - } else { - error!("`names()` arguments must be simple identifiers"); - } - } - } else if meta_item.has_name(sym::values) { - set_old_syntax(); - - if let Some((name, values)) = args.split_first() { - if name.is_word() && let Some(ident) = name.ident() { - let expected_values = check_cfg - .expecteds - .entry(ident.name) - .and_modify(|expected_values| match expected_values { - ExpectedValues::Some(_) => {} - ExpectedValues::Any => { - // handle the case where names(...) was done - // before values by changing to a list - *expected_values = ExpectedValues::Some(FxHashSet::default()); - } - }) - .or_insert_with(|| ExpectedValues::Some(FxHashSet::default())); + if !meta_item.has_name(sym::cfg) { + expected_error(); + } - let ExpectedValues::Some(expected_values) = expected_values else { - bug!("`expected_values` should be a list a values") - }; + let mut names = Vec::new(); + let mut values: FxHashSet<_> = Default::default(); - for val in values { - if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) { - expected_values.insert(Some(*s)); - } else { - error!("`values()` arguments must be string literals"); - } - } + let mut any_specified = false; + let mut values_specified = false; + let mut values_any_specified = false; - if values.is_empty() { - expected_values.insert(None); - } - } else { - error!("`values()` first argument must be a simple identifier"); + for arg in args { + if arg.is_word() + && let Some(ident) = arg.ident() + { + if values_specified { + error!("`cfg()` names cannot be after values"); } - } else if args.is_empty() { - check_cfg.exhaustive_values = true; - } else { - expected_error(); - } - } else if meta_item.has_name(sym::cfg) { - old_syntax = Some(false); - - let mut names = Vec::new(); - let mut values: FxHashSet<_> = Default::default(); - - let mut any_specified = false; - let mut values_specified = false; - let mut values_any_specified = false; - - for arg in args { - if arg.is_word() && let Some(ident) = arg.ident() { - if values_specified { - error!("`cfg()` names cannot be after values"); - } - names.push(ident); - } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { - if any_specified { - error!("`any()` cannot be specified multiple times"); - } - any_specified = true; - if !args.is_empty() { - error!("`any()` must be empty"); - } - } else if arg.has_name(sym::values) && let Some(args) = arg.meta_item_list() { - if names.is_empty() { - error!("`values()` cannot be specified before the names"); - } else if values_specified { - error!("`values()` cannot be specified multiple times"); - } - values_specified = true; - - for arg in args { - if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) { - values.insert(Some(*s)); - } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { - if values_any_specified { - error!("`any()` in `values()` cannot be specified multiple times"); - } - values_any_specified = true; - if !args.is_empty() { - error!("`any()` must be empty"); - } - } else { - error!("`values()` arguments must be string literals or `any()`"); + names.push(ident); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if any_specified { + error!("`any()` cannot be specified multiple times"); + } + any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else if arg.has_name(sym::values) + && let Some(args) = arg.meta_item_list() + { + if names.is_empty() { + error!("`values()` cannot be specified before the names"); + } else if values_specified { + error!("`values()` cannot be specified multiple times"); + } + values_specified = true; + + for arg in args { + if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) { + values.insert(Some(*s)); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if values_any_specified { + error!("`any()` in `values()` cannot be specified multiple times"); } + values_any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else { + error!("`values()` arguments must be string literals or `any()`"); } - } else { - error!( - "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" - ); } + } else { + error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"); } + } - if values.is_empty() && !values_any_specified && !any_specified { - values.insert(None); - } else if !values.is_empty() && values_any_specified { - error!( - "`values()` arguments cannot specify string literals and `any()` at the same time" - ); - } + if values.is_empty() && !values_any_specified && !any_specified { + values.insert(None); + } else if !values.is_empty() && values_any_specified { + error!( + "`values()` arguments cannot specify string literals and `any()` at the same time" + ); + } - if any_specified { - if names.is_empty() - && values.is_empty() - && !values_specified - && !values_any_specified - { - check_cfg.exhaustive_names = false; - } else { - error!("`cfg(any())` can only be provided in isolation"); - } + if any_specified { + if names.is_empty() && values.is_empty() && !values_specified && !values_any_specified { + check_cfg.exhaustive_names = false; } else { - for name in names { - check_cfg - .expecteds - .entry(name.name) - .and_modify(|v| match v { - ExpectedValues::Some(v) if !values_any_specified => { - v.extend(values.clone()) - } - ExpectedValues::Some(_) => *v = ExpectedValues::Any, - ExpectedValues::Any => {} - }) - .or_insert_with(|| { - if values_any_specified { - ExpectedValues::Any - } else { - ExpectedValues::Some(values.clone()) - } - }); - } + error!("`cfg(any())` can only be provided in isolation"); } } else { - expected_error(); + for name in names { + check_cfg + .expecteds + .entry(name.name) + .and_modify(|v| match v { + ExpectedValues::Some(v) if !values_any_specified => { + v.extend(values.clone()) + } + ExpectedValues::Some(_) => *v = ExpectedValues::Any, + ExpectedValues::Any => {} + }) + .or_insert_with(|| { + if values_any_specified { + ExpectedValues::Any + } else { + ExpectedValues::Some(values.clone()) + } + }); + } } } @@ -392,19 +314,23 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se // Set parallel mode before thread pool creation, which will create `Lock`s. rustc_data_structures::sync::set_dyn_thread_safe_mode(config.opts.unstable_opts.threads > 1); + // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread + let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); + early_dcx.initialize_checked_jobserver(); + util::run_in_thread_pool_with_globals( config.opts.edition, config.opts.unstable_opts.threads, || { crate::callbacks::setup_callbacks(); - let handler = EarlyErrorHandler::new(config.opts.error_format); + let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend { make_codegen_backend(&config.opts) } else { util::get_codegen_backend( - &handler, + &early_dcx, &config.opts.maybe_sysroot, config.opts.unstable_opts.codegen_backend.as_deref(), ) @@ -421,7 +347,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se ) { Ok(bundle) => bundle, Err(e) => { - handler.early_error(format!("failed to load fluent bundle: {e}")); + early_dcx.early_error(format!("failed to load fluent bundle: {e}")); } }; @@ -432,7 +358,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se let target_override = codegen_backend.target_override(&config.opts); let mut sess = rustc_session::build_session( - &handler, + early_dcx, config.opts, CompilerIO { input: config.input, @@ -454,12 +380,12 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se codegen_backend.init(&sess); - let cfg = parse_cfg(&handler, config.crate_cfg); + let cfg = parse_cfg(&sess.dcx(), config.crate_cfg); let mut cfg = config::build_configuration(&sess, cfg); util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); sess.parse_sess.config = cfg; - let mut check_cfg = parse_check_cfg(&handler, config.crate_check_cfg); + let mut check_cfg = parse_check_cfg(&sess.dcx(), config.crate_check_cfg); check_cfg.fill_well_known(&sess.target); sess.parse_sess.check_config = check_cfg; @@ -473,12 +399,18 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se sess.opts.untracked_state_hash = hasher.finish() } - let compiler = Compiler { - sess: Lrc::new(sess), - codegen_backend: Lrc::from(codegen_backend), - register_lints: config.register_lints, - override_queries: config.override_queries, - }; + // Even though the session holds the lint store, we can't build the + // lint store until after the session exists. And we wait until now + // so that `register_lints` sees the fully initialized session. + let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); + if let Some(register_lints) = config.register_lints.as_deref() { + register_lints(&sess, &mut lint_store); + sess.registered_lints = true; + } + sess.lint_store = Some(Lrc::new(lint_store)); + + let compiler = + Compiler { sess, codegen_backend, override_queries: config.override_queries }; rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { let r = { @@ -499,21 +431,21 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se } pub fn try_print_query_stack( - handler: &Handler, + dcx: &DiagCtxt, num_frames: Option<usize>, file: Option<std::fs::File>, ) { eprintln!("query stack during panic:"); // Be careful relying on global state here: this code is called from - // a panic hook, which means that the global `Handler` may be in a weird + // a panic hook, which means that the global `DiagCtxt` may be in a weird // state if it was responsible for triggering the panic. let i = ty::tls::with_context_opt(|icx| { if let Some(icx) = icx { ty::print::with_no_queries!(print_query_stack( QueryCtxt::new(icx.tcx), icx.query, - handler, + dcx, num_frames, file, )) diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index ffa2667a3..cfa464478 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -6,16 +6,12 @@ #![feature(let_chains)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - mod callbacks; mod errors; pub mod interface; @@ -32,4 +28,4 @@ pub use queries::Queries; #[cfg(test)] mod tests; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7d14d088e..21beb90d7 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; -use rustc_passes::{self, abi_test, hir_stats, layout_test}; +use rustc_passes::{abi_test, hir_stats, layout_test}; use rustc_resolve::Resolver; use rustc_session::code_stats::VTableSizeInfo; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; @@ -39,7 +39,7 @@ use std::any::Any; use std::ffi::OsString; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; -use std::sync::{Arc, LazyLock}; +use std::sync::LazyLock; use std::{env, fs, iter}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { @@ -56,7 +56,7 @@ pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { } if let Some(ref s) = sess.opts.unstable_opts.show_span { - rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate); + rustc_ast_passes::show_span::run(sess.dcx(), s, &krate); } if sess.opts.unstable_opts.hir_stats { @@ -72,17 +72,6 @@ fn count_nodes(krate: &ast::Crate) -> usize { counter.count } -pub(crate) fn create_lint_store( - sess: &Session, - register_lints: Option<impl Fn(&Session, &mut LintStore)>, -) -> LintStore { - let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); - if let Some(register_lints) = register_lints { - register_lints(sess, &mut lint_store); - } - lint_store -} - fn pre_expansion_lint<'a>( sess: &Session, features: &Features, @@ -125,7 +114,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { } } -/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, +/// Runs the "early phases" of the compiler: initial `cfg` processing, /// 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. @@ -138,7 +127,7 @@ fn configure_and_expand( let tcx = resolver.tcx(); let sess = tcx.sess; let features = tcx.features(); - let lint_store = unerased_lint_store(tcx); + let lint_store = unerased_lint_store(tcx.sess); let crate_name = tcx.crate_name(LOCAL_CRATE); let lint_check_node = (&krate, pre_configured_attrs); pre_expansion_lint( @@ -161,7 +150,7 @@ fn configure_and_expand( ) }); - util::check_attr_crate_type(sess, pre_configured_attrs, &mut resolver.lint_buffer()); + util::check_attr_crate_type(sess, pre_configured_attrs, resolver.lint_buffer()); // Expand all macros krate = sess.time("macro_expand_crate", || { @@ -278,7 +267,7 @@ fn configure_and_expand( is_proc_macro_crate, has_proc_macro_decls, is_test_crate, - sess.diagnostic(), + sess.dcx(), ) }); @@ -295,16 +284,16 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { - eprintln!("Post-expansion node count: {}", count_nodes(&krate)); + eprintln!("Post-expansion node count: {}", count_nodes(krate)); } if sess.opts.unstable_opts.hir_stats { - hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS", "ast-stats-2"); + hir_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2"); } // Needs to go *after* expansion to be able to check the results of macro expansion. sess.time("complete_gated_feature_checking", || { - rustc_ast_passes::feature_gate::check_crate(&krate, sess, tcx.features()); + rustc_ast_passes::feature_gate::check_crate(krate, sess, tcx.features()); }); // Add all buffered lints from the `ParseSess` to the `Session`. @@ -317,6 +306,8 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { + // We will soon sort, so the initial order does not matter. + #[allow(rustc::potential_query_instability)] let mut identifiers: Vec<_> = identifiers.drain().collect(); identifiers.sort_by_key(|&(key, _)| key); for (ident, mut spans) in identifiers.into_iter() { @@ -330,7 +321,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { } }); - let lint_store = unerased_lint_store(tcx); + let lint_store = unerased_lint_store(tcx.sess); rustc_lint::check_ast_node( sess, tcx.features(), @@ -442,6 +433,9 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P escape_dep_filename(&file.prefer_local().to_string()) }; + // The entries will be used to declare dependencies beween files in a + // Makefile-like output, so the iteration order does not matter. + #[allow(rustc::potential_query_instability)] let extra_tracked_files = file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str()))); files.extend(extra_tracked_files); @@ -497,6 +491,8 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P // Emit special comments with information about accessed environment variables. let env_depinfo = sess.parse_sess.env_depinfo.borrow(); if !env_depinfo.is_empty() { + // We will soon sort, so the initial order does not matter. + #[allow(rustc::potential_query_instability)] let mut envs: Vec<_> = env_depinfo .iter() .map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env))) @@ -530,13 +526,11 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P match result { Ok(_) => { if sess.opts.json_artifact_notifications { - sess.parse_sess - .span_diagnostic - .emit_artifact_notification(&deps_filename, "dep-info"); + sess.dcx().emit_artifact_notification(deps_filename, "dep-info"); } } Err(error) => { - sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error }); + sess.emit_fatal(errors::ErrorWritingDependencies { path: deps_filename, error }); } } } @@ -564,23 +558,27 @@ fn resolver_for_lowering<'tcx>( tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) } -fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> { +pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) { + // Make sure name resolution and macro expansion is run for + // the side-effect of providing a complete set of all + // accessed files and env vars. + let _ = tcx.resolver_for_lowering(()); + let sess = tcx.sess; - let _timer = sess.timer("prepare_outputs"); - let (_, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let _timer = sess.timer("write_dep_info"); let crate_name = tcx.crate_name(LOCAL_CRATE); - let outputs = util::build_output_filenames(&krate.attrs, sess); + let outputs = tcx.output_filenames(()); let output_paths = generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name); // Ensure the source file isn't accidentally overwritten during compilation. - if let Some(ref input_path) = sess.io.input.opt_path() { + if let Some(input_path) = sess.io.input.opt_path() { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path }); } - if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) { + if let Some(dir_path) = output_conflicts_with_dir(&output_paths) { sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory { input_path, dir_path, @@ -607,15 +605,12 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> { } } } - - 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; providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); @@ -645,7 +640,6 @@ pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, crate_types: Vec<CrateType>, stable_crate_id: StableCrateId, - lint_store: Lrc<LintStore>, dep_graph: DepGraph, untracked: Untracked, gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>, @@ -657,10 +651,10 @@ pub fn create_global_ctxt<'tcx>( // incr. comp. yet. dep_graph.assert_ignored(); - let sess = &compiler.session(); + let sess = &compiler.sess; let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); - let codegen_backend = compiler.codegen_backend(); + let codegen_backend = &compiler.codegen_backend; let mut providers = *DEFAULT_QUERY_PROVIDERS; codegen_backend.provide(&mut providers); @@ -676,7 +670,6 @@ pub fn create_global_ctxt<'tcx>( sess, crate_types, stable_crate_id, - lint_store, arena, hir_arena, untracked, @@ -769,7 +762,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); tcx.hir().par_body_owners(|def_id| { - if let rustc_hir::def::DefKind::Coroutine = tcx.def_kind(def_id) { + if tcx.is_coroutine(def_id.to_def_id()) { tcx.ensure().mir_coroutine_witnesses(def_id); tcx.ensure().check_coroutine_obligations(def_id); } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 3a5f788e8..8a553b95e 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -1,13 +1,14 @@ use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation}; use crate::interface::{Compiler, Result}; -use crate::{passes, util}; +use crate::{errors, passes, util}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; @@ -15,9 +16,11 @@ use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{GlobalCtxt, TyCtxt}; +use rustc_serialize::opaque::FileEncodeResult; use rustc_session::config::{self, CrateType, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; -use rustc_session::{output::find_crate_name, Session}; +use rustc_session::output::find_crate_name; +use rustc_session::Session; use rustc_span::symbol::sym; use std::any::Any; use std::cell::{RefCell, RefMut}; @@ -83,7 +86,6 @@ pub struct Queries<'tcx> { hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>, parse: Query<ast::Crate>, - pre_configure: Query<(ast::Crate, ast::AttrVec)>, // This just points to what's in `gcx_cell`. gcx: Query<&'tcx GlobalCtxt<'tcx>>, } @@ -96,29 +98,26 @@ impl<'tcx> Queries<'tcx> { arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), parse: Default::default(), - pre_configure: Default::default(), gcx: Default::default(), } } - fn session(&self) -> &Lrc<Session> { - &self.compiler.sess - } - fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> { - self.compiler.codegen_backend() + pub fn finish(&self) -> FileEncodeResult { + if let Some(gcx) = self.gcx_cell.get() { gcx.finish() } else { Ok(0) } } pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> { - self.parse - .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit())) + self.parse.compute(|| { + passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit()) + }) } - #[deprecated = "pre_configure may be made private in the future. If you need it please open an issue with your use case."] - pub fn pre_configure(&self) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec)>> { - self.pre_configure.compute(|| { + pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { + self.gcx.compute(|| { + let sess = &self.compiler.sess; + let mut krate = self.parse()?.steal(); - let sess = self.session(); rustc_builtin_macros::cmdline_attrs::inject( &mut krate, &sess.parse_sess, @@ -127,15 +126,6 @@ impl<'tcx> Queries<'tcx> { let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs); - Ok((krate, pre_configured_attrs)) - }) - } - - pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { - self.gcx.compute(|| { - let sess = self.session(); - #[allow(deprecated)] - let (krate, pre_configured_attrs) = self.pre_configure()?.steal(); // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. let crate_name = find_crate_name(sess, &pre_configured_attrs); @@ -146,12 +136,11 @@ impl<'tcx> Queries<'tcx> { sess.opts.cg.metadata.clone(), sess.cfg_version, ); + let outputs = util::build_output_filenames(&pre_configured_attrs, sess); let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; - let lint_store = - Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref())); let cstore = FreezeLock::new(Box::new(CStore::new( - self.codegen_backend().metadata_loader(), + self.compiler.codegen_backend.metadata_loader(), stable_crate_id, )) as _); let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); @@ -164,7 +153,6 @@ impl<'tcx> Queries<'tcx> { self.compiler, crate_types, stable_crate_id, - lint_store, dep_graph, untracked, &self.gcx_cell, @@ -183,25 +171,20 @@ impl<'tcx> Queries<'tcx> { crate_name, ))); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); + feed.output_filenames(Arc::new(outputs)); + + let feed = tcx.feed_local_def_id(CRATE_DEF_ID); + feed.def_kind(DefKind::Mod); }); Ok(qcx) }) } - pub fn ongoing_codegen(&'tcx self) -> Result<Box<dyn Any>> { + pub fn write_dep_info(&'tcx self) -> Result<()> { self.global_ctxt()?.enter(|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); - - Ok(passes::start_codegen(&**self.codegen_backend(), tcx)) - }) + passes::write_dep_info(tcx); + }); + Ok(()) } /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used @@ -211,16 +194,16 @@ impl<'tcx> Queries<'tcx> { let Some((def_id, _)) = tcx.entry_fn(()) else { return }; for attr in tcx.get_attrs(def_id, sym::rustc_error) { match attr.meta_item_list() { - // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`. + // Check if there is a `#[rustc_error(span_delayed_bug_from_inside_query)]`. Some(list) if list.iter().any(|list_item| { matches!( list_item.ident().map(|i| i.name), - Some(sym::delay_span_bug_from_inside_query) + Some(sym::span_delayed_bug_from_inside_query) ) }) => { - tcx.ensure().trigger_delay_span_bug(def_id); + tcx.ensure().trigger_span_delayed_bug(def_id); } // Bare `#[rustc_error]`. @@ -238,68 +221,61 @@ impl<'tcx> Queries<'tcx> { } } - pub fn linker(&'tcx self, ongoing_codegen: Box<dyn Any>) -> Result<Linker> { - let sess = self.session().clone(); - let codegen_backend = self.codegen_backend().clone(); + pub fn codegen_and_build_linker(&'tcx self) -> Result<Linker> { + self.global_ctxt()?.enter(|tcx| { + // Don't do code generation if there were any errors + self.compiler.sess.compile_status()?; - let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| { - ( - if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None }, - tcx.output_filenames(()).clone(), - tcx.dep_graph.clone(), - ) - }); + // 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.compiler.sess.dcx().flush_delayed(); - Ok(Linker { - sess, - codegen_backend, + // Hook for UI tests. + Self::check_for_rustc_errors_attr(tcx); - dep_graph, - prepare_outputs, - crate_hash, - ongoing_codegen, + let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx); + + Ok(Linker { + dep_graph: tcx.dep_graph.clone(), + output_filenames: tcx.output_filenames(()).clone(), + crate_hash: if tcx.needs_crate_hash() { + Some(tcx.crate_hash(LOCAL_CRATE)) + } else { + None + }, + ongoing_codegen, + }) }) } } pub struct Linker { - // compilation inputs - sess: Lrc<Session>, - codegen_backend: Lrc<dyn CodegenBackend>, - - // compilation outputs dep_graph: DepGraph, - prepare_outputs: Arc<OutputFilenames>, + output_filenames: Arc<OutputFilenames>, // Only present when incr. comp. is enabled. crate_hash: Option<Svh>, ongoing_codegen: Box<dyn Any>, } impl Linker { - pub fn link(self) -> Result<()> { - let (codegen_results, work_products) = self.codegen_backend.join_codegen( - self.ongoing_codegen, - &self.sess, - &self.prepare_outputs, - )?; + pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { + let (codegen_results, work_products) = + codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)?; - self.sess.compile_status()?; + sess.compile_status()?; - let sess = &self.sess; - let dep_graph = self.dep_graph; sess.time("serialize_work_products", || { - rustc_incremental::save_work_product_index(sess, &dep_graph, work_products) + rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products) }); - let prof = self.sess.prof.clone(); - prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph)); + let prof = sess.prof.clone(); + prof.generic_activity("drop_dep_graph").run(move || drop(self.dep_graph)); // Now that we won't touch anything in the incremental compilation directory // any more, we can finalize it (which involves renaming it) - rustc_incremental::finalize_session_directory(&self.sess, self.crate_hash); + rustc_incremental::finalize_session_directory(sess, self.crate_hash); - if !self - .sess + if !sess .opts .output_types .keys() @@ -309,14 +285,19 @@ impl Linker { } if sess.opts.unstable_opts.no_link { - let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT); - CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results) - .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; + let rlink_file = self.output_filenames.with_extension(config::RLINK_EXT); + CodegenResults::serialize_rlink( + sess, + &rlink_file, + &codegen_results, + &*self.output_filenames, + ) + .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; return Ok(()); } let _timer = sess.prof.verbose_generic_activity("link_crate"); - self.codegen_backend.link(&self.sess, codegen_results, &self.prepare_outputs) + codegen_backend.link(sess, codegen_results, &self.output_filenames) } } @@ -325,6 +306,7 @@ impl Compiler { where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T, { + // Must declare `_timer` first so that it is dropped after `queries`. let mut _timer = None; let queries = Queries::new(self); let ret = f(&queries); @@ -337,15 +319,19 @@ impl Compiler { // after this point, they'll show up as "<unknown>" in self-profiling data. { let _prof_timer = - queries.session().prof.generic_activity("self_profile_alloc_query_strings"); + queries.compiler.sess.prof.generic_activity("self_profile_alloc_query_strings"); gcx.enter(rustc_query_impl::alloc_self_profile_query_strings); } - self.session() - .time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); + self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); } - _timer = Some(self.session().timer("free_global_ctxt")); + // The timer's lifetime spans the dropping of `queries`, which contains + // the global context. + _timer = Some(self.sess.timer("free_global_ctxt")); + if let Err((path, error)) = queries.finish() { + self.sess.emit_err(errors::FailedWritingFile { path: &path, error }); + } ret } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index d30816955..04a7714d4 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -5,15 +5,15 @@ use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, - InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, - LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, OomStrategy, Options, OutFileName, - OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, - SwitchWithOptPath, SymbolManglingVersion, TraitSolver, WasiExecModel, + FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, + LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, NextSolverConfig, + OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use rustc_session::{build_session, getopts, CompilerIO, EarlyErrorHandler, Session}; +use rustc_session::{build_session, getopts, CompilerIO, EarlyDiagCtxt, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; @@ -24,10 +24,12 @@ use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::sync::Arc; -fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, Cfg) { +fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { + let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); + early_dcx.initialize_checked_jobserver(); + let registry = registry::Registry::new(&[]); - let sessopts = build_session_options(handler, &matches); - let cfg = parse_cfg(handler, matches.opt_strs("cfg")); + let sessopts = build_session_options(&mut early_dcx, &matches); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, @@ -36,7 +38,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se temps_dir, }; let sess = build_session( - handler, + early_dcx, sessopts, io, None, @@ -50,6 +52,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se Arc::default(), Default::default(), ); + let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg")); (sess, cfg) } @@ -116,8 +119,7 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) { fn test_switch_implies_cfg_test() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, cfg) = mk_session(&mut handler, matches); + let (sess, cfg) = mk_session(matches); let cfg = build_configuration(&sess, cfg); assert!(cfg.contains(&(sym::test, None))); }); @@ -128,8 +130,7 @@ fn test_switch_implies_cfg_test() { fn test_switch_implies_cfg_test_unless_cfg_test() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, cfg) = mk_session(&mut handler, matches); + let (sess, cfg) = mk_session(matches); let cfg = build_configuration(&sess, cfg); let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); assert!(test_items.next().is_some()); @@ -141,24 +142,21 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { fn test_can_print_warnings() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, _) = mk_session(&mut handler, matches); - assert!(!sess.diagnostic().can_emit_warnings()); + let (sess, _) = mk_session(matches); + assert!(!sess.dcx().can_emit_warnings()); }); rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, _) = mk_session(&mut handler, matches); - assert!(sess.diagnostic().can_emit_warnings()); + let (sess, _) = mk_session(matches); + assert!(sess.dcx().can_emit_warnings()); }); rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, _) = mk_session(&mut handler, matches); - assert!(sess.diagnostic().can_emit_warnings()); + let (sess, _) = mk_session(matches); + assert!(sess.dcx().can_emit_warnings()); }); } @@ -303,36 +301,36 @@ fn test_search_paths_tracking_hash_different_order() { let mut v3 = Options::default(); let mut v4 = Options::default(); - let handler = EarlyErrorHandler::new(JSON); + let early_dcx = EarlyDiagCtxt::new(JSON); const JSON: ErrorOutputType = ErrorOutputType::Json { pretty: false, json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), }; // Reference - v1.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); - v1.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); - v1.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); - v1.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); - v1.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - - v2.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); - v2.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); - v2.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); - v2.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); - v2.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - - v3.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); - v3.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); - v3.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); - v3.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); - v3.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - - v4.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - v4.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); - v4.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); - v4.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); - v4.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); + v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); + v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); + v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); + v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); + v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); + + v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); + v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); + v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); + v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); + v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); + + v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); + v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); + v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); + v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); + v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); + + v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno")); + v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc")); + v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def")); + v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi")); + v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl")); assert_same_hash(&v1, &v2); assert_same_hash(&v1, &v3); @@ -679,7 +677,6 @@ fn test_unstable_options_tracking_hash() { untracked!(incremental_info, true); untracked!(incremental_verify_ich, true); untracked!(input_stats, true); - untracked!(keep_hygiene_data, true); untracked!(link_native_libraries, false); untracked!(llvm_time_trace, true); untracked!(ls, vec!["all".to_owned()]); @@ -691,7 +688,6 @@ fn test_unstable_options_tracking_hash() { untracked!(no_leak_check, true); untracked!(no_parallel_llvm, true); untracked!(parse_only, true); - 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!(print_codegen_stats, true); @@ -751,6 +747,7 @@ fn test_unstable_options_tracking_hash() { tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); + tracked!(default_hidden_visibility, Some(true)); tracked!(dep_info_omit_d_target, true); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); @@ -760,6 +757,7 @@ fn test_unstable_options_tracking_hash() { tracked!(flatten_format_args, false); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); + tracked!(function_return, FunctionReturn::ThunkExtern); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(incremental_ignore_spans, true); @@ -771,6 +769,7 @@ fn test_unstable_options_tracking_hash() { tracked!(instrument_xray, Some(InstrumentXRay::default())); tracked!(link_directives, false); tracked!(link_only, true); + tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(maximal_hir_to_mir_coverage, true); @@ -781,6 +780,10 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); + tracked!( + next_solver, + Some(NextSolverConfig { coherence: true, globally: false, dump_tree: Default::default() }) + ); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); @@ -822,7 +825,6 @@ fn test_unstable_options_tracking_hash() { tracked!(thir_unsafeck, true); tracked!(tiny_const_eval_limit, true); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); - tracked!(trait_solver, TraitSolver::NextCoherence); tracked!(translate_remapped_path_to_local_path, false); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); @@ -852,9 +854,9 @@ fn test_edition_parsing() { let options = Options::default(); assert!(options.edition == DEFAULT_EDITION); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let sessopts = build_session_options(&mut handler, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches); assert!(sessopts.edition == Edition::Edition2018) } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 22d127934..bffa74321 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -14,7 +14,7 @@ use rustc_session::{filesearch, output, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; -use session::EarlyErrorHandler; +use session::EarlyDiagCtxt; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::mem; @@ -107,7 +107,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( use rustc_query_impl::QueryCtxt; use rustc_query_system::query::{deadlock, QueryContext}; - let registry = sync::Registry::new(threads); + let registry = sync::Registry::new(std::num::NonZeroUsize::new(threads).unwrap()); if !sync::is_dyn_thread_safe() { return run_in_thread_with_globals(edition, || { @@ -126,11 +126,8 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( .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 = FromDyn::from(tls::with(|tcx| { - QueryCtxt::new(tcx) - .try_collect_active_jobs() - .expect("active jobs shouldn't be locked in deadlock handler") - })); + let query_map = + FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())); let registry = rayon_core::Registry::current(); thread::spawn(move || deadlock(query_map.into_inner(), ®istry)); }); @@ -164,16 +161,16 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( }) } -fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBackendFn { +fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn { let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {path:?}: {err}"); - handler.early_error(err); + early_dcx.early_error(err); }); let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") } .unwrap_or_else(|e| { let err = format!("couldn't load codegen backend: {e}"); - handler.early_error(err); + early_dcx.early_error(err); }); // Intentionally leak the dynamic library. We can't ever unload it @@ -188,7 +185,7 @@ fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBack /// /// A name of `None` indicates that the default backend should be used. pub fn get_codegen_backend( - handler: &EarlyErrorHandler, + early_dcx: &EarlyDiagCtxt, maybe_sysroot: &Option<PathBuf>, backend_name: Option<&str>, ) -> Box<dyn CodegenBackend> { @@ -199,11 +196,11 @@ pub fn get_codegen_backend( match backend_name.unwrap_or(default_codegen_backend) { filename if filename.contains('.') => { - load_backend_from_dylib(handler, filename.as_ref()) + load_backend_from_dylib(early_dcx, filename.as_ref()) } #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, - backend_name => get_codegen_sysroot(handler, maybe_sysroot, backend_name), + backend_name => get_codegen_sysroot(early_dcx, maybe_sysroot, backend_name), } }); @@ -236,7 +233,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> { } fn get_codegen_sysroot( - handler: &EarlyErrorHandler, + early_dcx: &EarlyDiagCtxt, maybe_sysroot: &Option<PathBuf>, backend_name: &str, ) -> MakeBackendFn { @@ -274,7 +271,7 @@ fn get_codegen_sysroot( "failed to find a `codegen-backends` folder \ in the sysroot candidates:\n* {candidates}" ); - handler.early_error(err); + early_dcx.early_error(err); }); info!("probing {} for a codegen backend", sysroot.display()); @@ -285,7 +282,7 @@ fn get_codegen_sysroot( sysroot.display(), e ); - handler.early_error(err); + early_dcx.early_error(err); }); let mut file: Option<PathBuf> = None; @@ -313,16 +310,16 @@ fn get_codegen_sysroot( prev.display(), path.display() ); - handler.early_error(err); + early_dcx.early_error(err); } file = Some(path.clone()); } match file { - Some(ref s) => load_backend_from_dylib(handler, s), + Some(ref s) => load_backend_from_dylib(early_dcx, s), None => { let err = format!("unsupported builtin codegen backend `{backend_name}`"); - handler.early_error(err); + early_dcx.early_error(err); } } } @@ -415,7 +412,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C let mut base = session.opts.crate_types.clone(); if base.is_empty() { let attr_types = attrs.iter().filter_map(|a| { - if a.has_name(sym::crate_type) && let Some(s) = a.value_str() { + if a.has_name(sym::crate_type) + && let Some(s) = a.value_str() + { categorize_crate_type(s) } else { None |