diff options
Diffstat (limited to 'compiler/rustc_interface/src')
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 54 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/lib.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/queries.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 81 | 
6 files changed, 120 insertions, 78 deletions
| diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c5b81dbd679..5254a6576f9 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -11,7 +11,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxt, ErrorGuaranteed}; use rustc_lint::LintStore; - use rustc_middle::ty; use rustc_middle::ty::CurrentGcx; use rustc_middle::util::Providers; @@ -28,6 +27,7 @@ use rustc_span::FileName; use std::path::PathBuf; use std::result; use std::sync::Arc; +use tracing::trace; pub type Result<T> = result::Result<T, ErrorGuaranteed>; @@ -120,14 +120,45 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg { ); let filename = FileName::cfg_spec_source_code(&s); + const VISIT: &str = + "visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details"; + macro_rules! error { ($reason:expr) => { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - dcx.fatal(format!( - concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), - s - )) + { + let mut diag = + dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); + diag.note($reason); + diag.note(VISIT); + diag.emit() + } + }; + (in $arg:expr, $reason:expr) => { + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + { + let mut diag = + dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); + + let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg); + if let Some(lit) = $arg.lit() { + let (lit_kind_article, lit_kind_descr) = { + let lit_kind = lit.as_token_lit().kind; + (lit_kind.article(), lit_kind.descr()) + }; + diag.note(format!( + "`{pparg}` is {lit_kind_article} {lit_kind_descr} literal" + )); + } else { + diag.note(format!("`{pparg}` is invalid")); + } + + diag.note($reason); + diag.note(VISIT); + diag.emit() + } }; } @@ -183,7 +214,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg { } any_specified = true; if !args.is_empty() { - error!("`any()` must be empty"); + error!(in arg, "`any()` takes no argument"); } } else if arg.has_name(sym::values) && let Some(args) = arg.meta_item_list() @@ -202,25 +233,25 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg { && let Some(args) = arg.meta_item_list() { if values_any_specified { - error!("`any()` in `values()` cannot be specified multiple times"); + error!(in arg, "`any()` in `values()` cannot be specified multiple times"); } values_any_specified = true; if !args.is_empty() { - error!("`any()` must be empty"); + error!(in arg, "`any()` in `values()` takes no argument"); } } else if arg.has_name(sym::none) && let Some(args) = arg.meta_item_list() { values.insert(None); if !args.is_empty() { - error!("`none()` must be empty"); + error!(in arg, "`none()` in `values()` takes no argument"); } } else { - error!("`values()` arguments must be string literals, `none()` or `any()`"); + error!(in arg, "`values()` arguments must be string literals, `none()` or `any()`"); } } } else { - error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"); + error!(in arg, "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"); } } @@ -358,6 +389,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target); util::run_in_thread_pool_with_globals( + &early_dcx, config.opts.edition, config.opts.unstable_opts.threads, SourceMapInputs { file_loader, path_mapping, hash_kind }, diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index d0ce23dacb5..8b1d9b706ca 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,13 +1,8 @@ #![feature(decl_macro)] -#![feature(generic_nonzero)] -#![feature(lazy_cell)] #![feature(let_chains)] #![feature(thread_spawn_unchecked)] #![feature(try_blocks)] -#[macro_use] -extern crate tracing; - mod callbacks; mod errors; pub mod interface; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 91cef02c7d1..33995f80162 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -4,7 +4,6 @@ use crate::proc_macro_decls; use crate::util; 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; @@ -20,7 +19,6 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; 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::{abi_test, hir_stats, layout_test}; use rustc_resolve::Resolver; @@ -41,6 +39,7 @@ use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; use std::sync::LazyLock; use std::{env, fs, iter}; +use tracing::{info, instrument}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { let krate = sess.time("parse_crate", || match &sess.io.input { @@ -460,7 +459,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { let source = tcx.used_crate_source(cnum); if let Some((path, _)) = &source.dylib { files.push(escape_dep_filename(&path.display().to_string())); @@ -616,8 +615,8 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); - mir_borrowck::provide(providers); - mir_build::provide(providers); + rustc_borrowck::provide(providers); + rustc_mir_build::provide(providers); rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); @@ -759,7 +758,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.hir().par_body_owners(|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); + tcx.ensure().check_coroutine_obligations( + tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), + ); } }); sess.time("layout_testing", || layout_test::test_layout(tcx)); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index ee677a092e2..1b9165342d4 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -8,7 +8,7 @@ use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; -use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; +use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; use rustc_metadata::creader::CStore; @@ -140,11 +140,16 @@ impl<'tcx> Queries<'tcx> { let cstore = FreezeLock::new(Box::new(CStore::new( self.compiler.codegen_backend.metadata_loader(), - stable_crate_id, )) as _); let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); - let untracked = - Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions }; + + let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default()); + let untracked = Untracked { + cstore, + source_span: AppendOnlyIndexVec::new(), + definitions, + stable_crate_ids, + }; let qcx = passes::create_global_ctxt( self.compiler, @@ -158,7 +163,8 @@ impl<'tcx> Queries<'tcx> { ); qcx.enter(|tcx| { - let feed = tcx.feed_local_crate(); + let feed = tcx.create_crate_num(stable_crate_id).unwrap(); + assert_eq!(feed.key(), LOCAL_CRATE); feed.crate_name(crate_name); let feed = tcx.feed_unit_query(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index e563728c893..c6cf7cf4f3f 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,12 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - CollapseMacroDebuginfo, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, - ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, - InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, - NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, - Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, - WasiExecModel, + CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, + ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, + Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, + LtoCli, 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; @@ -19,7 +19,9 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; -use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; +use rustc_target::spec::{ + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, +}; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; use std::num::NonZero; @@ -319,6 +321,7 @@ fn test_search_paths_tracking_hash_different_order() { &opts.target_triple, &early_dcx, search_path, + false, )); }; @@ -597,6 +600,7 @@ fn test_codegen_options_tracking_hash() { // Make sure that changing a [TRACKED] option changes the hash. // tidy-alphabetical-start tracked!(code_model, Some(CodeModel::Large)); + tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); tracked!(control_flow_guard, CFGuard::Checks); tracked!(debug_assertions, Some(true)); tracked!(debuginfo, DebugInfo::Limited); @@ -757,12 +761,10 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); - tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); - tracked!(coverage_options, CoverageOptions { branch: true }); + tracked!(coverage_options, CoverageOptions { level: CoverageLevel::Mcdc }); tracked!(crate_attr, vec!["abc".to_string()]); 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!(direct_access_external_data, Some(true)); @@ -797,16 +799,14 @@ 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!(next_solver, Some(NextSolverConfig { coherence: true, globally: false })); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); tracked!(no_profiler_runtime, true); tracked!(no_trait_vptr, true); tracked!(no_unique_section_names, true); + tracked!(on_broken_pipe, OnBrokenPipe::Kill); tracked!(oom, OomStrategy::Panic); tracked!(osx_rpath_install_name, true); tracked!(packed_bundled_libs, true); @@ -851,6 +851,7 @@ fn test_unstable_options_tracking_hash() { tracked!(verify_llvm_ir, true); tracked!(virtual_function_elimination, true); tracked!(wasi_exec_model, Some(WasiExecModel::Reactor)); + tracked!(wasm_c_abi, WasmCAbi::Spec); // tidy-alphabetical-end macro_rules! tracked_no_crate_hash { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 02dcfe9c8df..8dac524bb5b 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,5 +1,4 @@ use crate::errors; -use info; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; #[cfg(parallel_compiler)] @@ -7,24 +6,23 @@ use rustc_data_structures::sync; use rustc_metadata::{load_symbol_from_dylib, DylibError}; use rustc_middle::ty::CurrentGcx; use rustc_parse::validate_attr; -use rustc_session as session; -use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{host_triple, Cfg, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; -use rustc_session::{filesearch, Session}; +use rustc_session::output::{categorize_crate_type, CRATE_TYPES}; +use rustc_session::{filesearch, EarlyDiagCtxt, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; use rustc_span::symbol::sym; use rustc_target::spec::Target; -use session::output::{categorize_crate_type, CRATE_TYPES}; -use session::EarlyDiagCtxt; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::OnceLock; use std::thread; use std::{env, iter}; +use tracing::info; /// Function pointer type that constructs a new CodegenBackend. pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; @@ -53,20 +51,38 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy pub static STACK_SIZE: OnceLock<usize> = OnceLock::new(); pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024; -fn init_stack_size() -> usize { +fn init_stack_size(early_dcx: &EarlyDiagCtxt) -> usize { // Obey the environment setting or default *STACK_SIZE.get_or_init(|| { env::var_os("RUST_MIN_STACK") - .map(|os_str| os_str.to_string_lossy().into_owned()) - // ignore if it is set to nothing - .filter(|s| s.trim() != "") - .map(|s| s.trim().parse::<usize>().unwrap()) + .as_ref() + .map(|os_str| os_str.to_string_lossy()) + // if someone finds out `export RUST_MIN_STACK=640000` isn't enough stack + // they might try to "unset" it by running `RUST_MIN_STACK= rustc code.rs` + // this is wrong, but std would nonetheless "do what they mean", so let's do likewise + .filter(|s| !s.trim().is_empty()) + // rustc is a batch program, so error early on inputs which are unlikely to be intended + // so no one thinks we parsed them setting `RUST_MIN_STACK="64 megabytes"` + // FIXME: we could accept `RUST_MIN_STACK=64MB`, perhaps? + .map(|s| { + let s = s.trim(); + // FIXME(workingjubilee): add proper diagnostics when we factor out "pre-run" setup + #[allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)] + s.parse::<usize>().unwrap_or_else(|_| { + let mut err = early_dcx.early_struct_fatal(format!( + r#"`RUST_MIN_STACK` should be a number of bytes, but was "{s}""#, + )); + err.note("you can also unset `RUST_MIN_STACK` to use the default stack size"); + err.emit() + }) + }) // otherwise pick a consistent default .unwrap_or(DEFAULT_STACK_SIZE) }) } fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( + thread_stack_size: usize, edition: Edition, sm_inputs: SourceMapInputs, f: F, @@ -77,7 +93,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( // 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 builder = thread::Builder::new().name("rustc".to_string()).stack_size(init_stack_size()); + let builder = thread::Builder::new().name("rustc".to_string()).stack_size(thread_stack_size); // We build the session globals and run `f` on the spawned thread, because // `SessionGlobals` does not impl `Send` in the non-parallel compiler. @@ -102,16 +118,19 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( #[cfg(not(parallel_compiler))] pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( + thread_builder_diag: &EarlyDiagCtxt, edition: Edition, _threads: usize, sm_inputs: SourceMapInputs, f: F, ) -> R { - run_in_thread_with_globals(edition, sm_inputs, f) + let thread_stack_size = init_stack_size(thread_builder_diag); + run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, f) } #[cfg(parallel_compiler)] pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( + thread_builder_diag: &EarlyDiagCtxt, edition: Edition, threads: usize, sm_inputs: SourceMapInputs, @@ -123,10 +142,12 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, use rustc_query_system::query::{break_query_cycles, QueryContext}; use std::process; + let thread_stack_size = init_stack_size(thread_builder_diag); + let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap()); if !sync::is_dyn_thread_safe() { - return run_in_thread_with_globals(edition, sm_inputs, |current_gcx| { + return run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, |current_gcx| { // Register the thread for use with the `WorkerLocal` type. registry.register(); @@ -169,7 +190,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, }) .unwrap(); }) - .stack_size(init_stack_size()); + .stack_size(thread_stack_size); // 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 @@ -286,7 +307,7 @@ fn get_codegen_sysroot( "cannot load the default codegen backend twice" ); - let target = session::config::host_triple(); + let target = host_triple(); let sysroot_candidates = sysroot_candidates(); let sysroot = iter::once(sysroot) @@ -378,31 +399,17 @@ pub(crate) fn check_attr_crate_type( if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() { let span = spanned.span; - let lev_candidate = find_best_match_for_name( + let candidate = find_best_match_for_name( &CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(), n, None, ); - if let Some(candidate) = lev_candidate { - lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value", - BuiltinLintDiag::UnknownCrateTypes( - span, - "did you mean".to_string(), - format!("\"{candidate}\""), - ), - ); - } else { - lint_buffer.buffer_lint( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value", - ); - } + lint_buffer.buffer_lint( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + BuiltinLintDiag::UnknownCrateTypes { span, candidate }, + ); } } else { // This is here mainly to check for using a macro, such as | 
