diff options
Diffstat (limited to 'compiler/rustc_interface/src')
| -rw-r--r-- | compiler/rustc_interface/src/callbacks.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/errors.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/lib.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 397 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/queries.rs | 210 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 43 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 82 |
8 files changed, 365 insertions, 471 deletions
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 76442de69d3..bc6d7c20997 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -10,6 +10,7 @@ //! origin crate when the `TyCtxt` is not present in TLS. use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS}; +use rustc_middle::dep_graph::TaskDepsRef; use rustc_middle::ty::tls; use std::fmt; @@ -26,14 +27,22 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { /// This is a callback from `rustc_ast` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used when diagnostic messages are /// emitted and stores them in the current query, if there is one. -fn track_diagnostic(diagnostic: &Diagnostic) { +fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { tls::with_context_opt(|icx| { if let Some(icx) = icx { if let Some(diagnostics) = icx.diagnostics { let mut diagnostics = diagnostics.lock(); diagnostics.extend(Some(diagnostic.clone())); + std::mem::drop(diagnostics); } + + // Diagnostics are tracked, we can ignore the dependency. + let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() }; + return tls::enter_context(&icx, move || (*f)(diagnostic)); } + + // In any other case, invoke diagnostics anyway. + (*f)(diagnostic); }) } @@ -55,5 +64,5 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> pub fn setup_callbacks() { rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); - TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_))); + TRACK_DIAGNOSTICS.swap(&(track_diagnostic as _)); } diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index f5135c78dc8..0eedee25026 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,5 +1,7 @@ use rustc_macros::Diagnostic; +use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; +use rustc_target::spec::TargetTriple; use std::io; use std::path::Path; @@ -30,10 +32,6 @@ pub struct MixedBinCrate; pub struct MixedProcMacroCrate; #[derive(Diagnostic)] -#[diag(interface_proc_macro_doc_without_arg)] -pub struct ProcMacroDocWithoutArg; - -#[derive(Diagnostic)] #[diag(interface_error_writing_dependencies)] pub struct ErrorWritingDependencies<'a> { pub path: &'a Path, @@ -87,3 +85,26 @@ pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } + +#[derive(Diagnostic)] +#[diag(interface_proc_macro_crate_panic_abort)] +pub struct ProcMacroCratePanicAbort; + +#[derive(Diagnostic)] +#[diag(interface_unsupported_crate_type_for_target)] +pub struct UnsupportedCrateTypeForTarget<'a> { + pub crate_type: CrateType, + pub target_triple: &'a TargetTriple, +} + +#[derive(Diagnostic)] +#[diag(interface_multiple_output_types_adaption)] +pub struct MultipleOutputTypesAdaption; + +#[derive(Diagnostic)] +#[diag(interface_ignoring_extra_filename)] +pub struct IgnoringExtraFilename; + +#[derive(Diagnostic)] +#[diag(interface_ignoring_out_dir)] +pub struct IgnoringOutDir; diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 89aaa0b95e4..5e38ca034ac 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -1,4 +1,3 @@ -pub use crate::passes::BoxedResolver; use crate::util; use rustc_ast::token; @@ -14,10 +13,10 @@ use rustc_middle::ty; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_session::config::{self, CheckCfg, ErrorOutputType, Input, OutputFilenames}; -use rustc_session::early_error; use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; use rustc_session::Session; +use rustc_session::{early_error, CompilerIO}; use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use std::path::PathBuf; @@ -35,11 +34,6 @@ pub type Result<T> = result::Result<T, ErrorGuaranteed>; pub struct Compiler { pub(crate) sess: Lrc<Session>, codegen_backend: Lrc<Box<dyn CodegenBackend>>, - pub(crate) input: Input, - pub(crate) input_path: Option<PathBuf>, - pub(crate) output_dir: Option<PathBuf>, - pub(crate) output_file: Option<PathBuf>, - pub(crate) temps_dir: Option<PathBuf>, pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>, pub(crate) override_queries: Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>, @@ -52,18 +46,6 @@ impl Compiler { pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> { &self.codegen_backend } - pub fn input(&self) -> &Input { - &self.input - } - pub fn output_dir(&self) -> &Option<PathBuf> { - &self.output_dir - } - pub fn output_file(&self) -> &Option<PathBuf> { - &self.output_file - } - pub fn temps_dir(&self) -> &Option<PathBuf> { - &self.temps_dir - } pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> { &self.register_lints } @@ -72,14 +54,7 @@ impl Compiler { sess: &Session, attrs: &[ast::Attribute], ) -> OutputFilenames { - util::build_output_filenames( - &self.input, - &self.output_dir, - &self.output_file, - &self.temps_dir, - attrs, - sess, - ) + util::build_output_filenames(attrs, sess) } } @@ -90,8 +65,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String .into_iter() .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( - "this error occurred on the command line: `--cfg={}`", - s + "this error occurred on the command line: `--cfg={s}`" ))); let filename = FileName::cfg_spec_source_code(&s); @@ -150,8 +124,7 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { 'specs: for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( - "this error occurred on the command line: `--check-cfg={}`", - s + "this error occurred on the command line: `--check-cfg={s}`" ))); let filename = FileName::cfg_spec_source_code(&s); @@ -194,7 +167,7 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { for val in values { if let Some(LitKind::Str(s, _)) = - val.literal().map(|lit| &lit.kind) + val.lit().map(|lit| &lit.kind) { ident_values.insert(s.to_string()); } else { @@ -246,10 +219,10 @@ pub struct Config { pub crate_check_cfg: CheckCfg, pub input: Input, - pub input_path: Option<PathBuf>, pub output_dir: Option<PathBuf>, pub output_file: Option<PathBuf>, pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>, + pub locale_resources: &'static [&'static str], pub lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -289,12 +262,20 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se crate::callbacks::setup_callbacks(); let registry = &config.registry; + + let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let (mut sess, codegen_backend) = util::create_session( config.opts, config.crate_cfg, config.crate_check_cfg, + config.locale_resources, config.file_loader, - config.input_path.clone(), + CompilerIO { + input: config.input, + output_dir: config.output_dir, + output_file: config.output_file, + temps_dir, + }, config.lint_caps, config.make_codegen_backend, registry.clone(), @@ -304,16 +285,9 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se 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, }; diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 542b638bbd7..1abbe8d4fab 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -3,6 +3,7 @@ #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(once_cell)] +#![feature(try_blocks)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -11,6 +12,9 @@ #[macro_use] extern crate tracing; +use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; +use rustc_macros::fluent_messages; + mod callbacks; mod errors; pub mod interface; @@ -26,3 +30,5 @@ pub use queries::Queries; #[cfg(test)] mod tests; + +fluent_messages! { "../locales/en-US.ftl" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7f1d21bf1d8..81c1d665ef0 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,8 +1,4 @@ -use crate::errors::{ - CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, - GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, - MixedProcMacroCrate, OutDirError, ProcMacroDocWithoutArg, TempsDirError, -}; +use crate::errors; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; use crate::util; @@ -12,11 +8,12 @@ use rustc_ast::{self as ast, visit}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; +use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; -use rustc_errors::{ErrorGuaranteed, PResult}; +use rustc_errors::PResult; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; -use rustc_hir::def_id::StableCrateId; -use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; +use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; @@ -27,29 +24,26 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_a use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; -use rustc_resolve::{Resolver, ResolverArenas}; +use rustc_resolve::Resolver; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; +use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, Untracked}; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::FileName; +use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; use std::any::Any; -use std::cell::RefCell; use std::ffi::OsString; use std::io::{self, BufWriter, Write}; -use std::marker::PhantomPinned; use std::path::{Path, PathBuf}; -use std::pin::Pin; -use std::rc::Rc; -use std::sync::LazyLock; +use std::sync::{Arc, LazyLock}; use std::{env, fs, iter}; -pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> { - let krate = sess.time("parse_crate", || match input { +pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { + let krate = sess.time("parse_crate", || match &sess.io.input { Input::File(file) => parse_crate_from_file(file, &sess.parse_sess), Input::Str { input, name } => { parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess) @@ -78,99 +72,12 @@ fn count_nodes(krate: &ast::Crate) -> usize { counter.count } -pub use boxed_resolver::BoxedResolver; -mod boxed_resolver { - use super::*; - - pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>); - - struct BoxedResolverInner { - session: Lrc<Session>, - resolver_arenas: Option<ResolverArenas<'static>>, - resolver: Option<Resolver<'static>>, - _pin: PhantomPinned, - } - - // Note: Drop order is important to prevent dangling references. Resolver must be dropped first, - // then resolver_arenas and session. - impl Drop for BoxedResolverInner { - fn drop(&mut self) { - self.resolver.take(); - self.resolver_arenas.take(); - } - } - - impl BoxedResolver { - pub(super) fn new( - session: Lrc<Session>, - make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>, - ) -> BoxedResolver { - let mut boxed_resolver = Box::new(BoxedResolverInner { - session, - resolver_arenas: Some(Resolver::arenas()), - resolver: None, - _pin: PhantomPinned, - }); - // SAFETY: `make_resolver` takes a resolver arena with an arbitrary lifetime and - // returns a resolver with the same lifetime as the arena. We ensure that the arena - // outlives the resolver in the drop impl and elsewhere so these transmutes are sound. - unsafe { - let resolver = make_resolver( - std::mem::transmute::<&Session, &Session>(&boxed_resolver.session), - std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>( - boxed_resolver.resolver_arenas.as_ref().unwrap(), - ), - ); - boxed_resolver.resolver = Some(resolver); - BoxedResolver(Pin::new_unchecked(boxed_resolver)) - } - } - - pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R { - // SAFETY: The resolver doesn't need to be pinned. - let mut resolver = unsafe { - self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver) - }; - f((&mut *resolver).as_mut().unwrap()) - } - - pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs { - match Rc::try_unwrap(resolver) { - Ok(resolver) => { - let mut resolver = resolver.into_inner(); - // SAFETY: The resolver doesn't need to be pinned. - let mut resolver = unsafe { - resolver - .0 - .as_mut() - .map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver) - }; - resolver.take().unwrap().into_outputs() - } - Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()), - } - } - } -} - -pub fn create_resolver( - sess: Lrc<Session>, - metadata_loader: Box<MetadataLoaderDyn>, - krate: &ast::Crate, - crate_name: &str, -) -> BoxedResolver { - trace!("create_resolver"); - BoxedResolver::new(sess, move |sess, resolver_arenas| { - Resolver::new(sess, krate, crate_name, metadata_loader, resolver_arenas) - }) -} - pub fn register_plugins<'a>( sess: &'a Session, metadata_loader: &'a dyn MetadataLoader, register_lints: impl Fn(&Session, &mut LintStore), mut krate: ast::Crate, - crate_name: &str, + crate_name: Symbol, ) -> Result<(ast::Crate, LintStore)> { krate = sess.time("attributes_injection", || { rustc_builtin_macros::cmdline_attrs::inject( @@ -207,10 +114,7 @@ pub fn register_plugins<'a>( }); } - let mut lint_store = rustc_lint::new_lint_store( - sess.opts.unstable_opts.no_interleave_lints, - sess.enable_internal_lints(), - ); + let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); register_lints(sess, &mut lint_store); let registrars = @@ -230,19 +134,21 @@ fn pre_expansion_lint<'a>( lint_store: &LintStore, registered_tools: &RegisteredTools, check_node: impl EarlyCheckNode<'a>, - node_name: &str, + node_name: Symbol, ) { - sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| { - rustc_lint::check_ast_node( - sess, - true, - lint_store, - registered_tools, - None, - rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), - check_node, - ); - }); + sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run( + || { + rustc_lint::check_ast_node( + sess, + true, + lint_store, + registered_tools, + None, + rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), + check_node, + ); + }, + ); } // Cannot implement directly for `LintStore` due to trait coherence. @@ -256,7 +162,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { node_id: ast::NodeId, attrs: &[ast::Attribute], items: &[rustc_ast::ptr::P<ast::Item>], - name: &str, + name: Symbol, ) { pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name); } @@ -266,14 +172,12 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the /// standard library and prelude, and name resolution. -pub fn configure_and_expand( - sess: &Session, - lint_store: &LintStore, - mut krate: ast::Crate, - crate_name: &str, - resolver: &mut Resolver<'_>, -) -> Result<ast::Crate> { - trace!("configure_and_expand"); +#[instrument(level = "trace", skip(krate, resolver))] +fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>) -> ast::Crate { + let tcx = resolver.tcx(); + let sess = tcx.sess; + let lint_store = unerased_lint_store(tcx); + let crate_name = tcx.crate_name(LOCAL_CRATE); pre_expansion_lint(sess, lint_store, resolver.registered_tools(), &krate, crate_name); rustc_builtin_macros::register_builtin_macros(resolver); @@ -344,20 +248,19 @@ pub fn configure_and_expand( ecx.check_unused_macros(); }); - let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); + // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed + // with a large AST + if ecx.reduced_recursion_limit.is_some() { + sess.abort_if_errors(); + unreachable!(); + } if cfg!(windows) { env::set_var("PATH", &old_path); } - if recursion_limit_hit { - // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed - // with a large AST - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } else { - Ok(krate) - } - })?; + krate + }); sess.time("maybe_building_test_harness", || { rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate) @@ -373,36 +276,30 @@ pub fn configure_and_expand( if crate_types.len() > 1 { if is_executable_crate { - sess.emit_err(MixedBinCrate); + sess.emit_err(errors::MixedBinCrate); } if is_proc_macro_crate { - sess.emit_err(MixedProcMacroCrate); + sess.emit_err(errors::MixedProcMacroCrate); } } - // For backwards compatibility, we don't try to run proc macro injection - // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being - // specified. This should only affect users who manually invoke 'rustdoc', as - // 'cargo doc' will automatically pass the proper '--crate-type' flags. - // However, we do emit a warning, to let such users know that they should - // start passing '--crate-type proc-macro' - if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { - sess.emit_warning(ProcMacroDocWithoutArg); - } else { - krate = sess.time("maybe_create_a_macro_crate", || { - let is_test_crate = sess.opts.test; - rustc_builtin_macros::proc_macro_harness::inject( - sess, - resolver, - krate, - is_proc_macro_crate, - has_proc_macro_decls, - is_test_crate, - sess.diagnostic(), - ) - }); + if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { + sess.emit_warning(errors::ProcMacroCratePanicAbort); } + krate = sess.time("maybe_create_a_macro_crate", || { + let is_test_crate = sess.opts.test; + rustc_builtin_macros::proc_macro_harness::inject( + sess, + resolver, + krate, + is_proc_macro_crate, + has_proc_macro_decls, + is_test_crate, + sess.diagnostic(), + ) + }); + // Done with macro expansion! if sess.opts.unstable_opts.input_stats { @@ -436,9 +333,9 @@ pub fn configure_and_expand( spans.sort(); if ident == sym::ferris { let first_span = spans[0]; - sess.emit_err(FerrisIdentifier { spans, first_span }); + sess.emit_err(errors::FerrisIdentifier { spans, first_span }); } else { - sess.emit_err(EmojiIdentifier { spans, ident }); + sess.emit_err(errors::EmojiIdentifier { spans, ident }); } } }); @@ -456,7 +353,7 @@ pub fn configure_and_expand( ) }); - Ok(krate) + krate } // Returns all the paths that correspond to generated files. @@ -464,7 +361,7 @@ fn generated_output_paths( sess: &Session, outputs: &OutputFilenames, exact_name: bool, - crate_name: &str, + crate_name: Symbol, ) -> Vec<PathBuf> { let mut out_filenames = Vec::new(); for output_type in sess.opts.output_types.keys() { @@ -543,7 +440,7 @@ fn escape_dep_env(symbol: Symbol) -> String { fn write_out_deps( sess: &Session, - boxed_resolver: &RefCell<BoxedResolver>, + cstore: &CrateStoreDyn, outputs: &OutputFilenames, out_filenames: &[PathBuf], ) { @@ -553,7 +450,7 @@ fn write_out_deps( } let deps_filename = outputs.path(OutputType::DepInfo); - let result = (|| -> io::Result<()> { + let result: io::Result<()> = try { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let mut files: Vec<String> = sess @@ -595,20 +492,19 @@ fn write_out_deps( } } - boxed_resolver.borrow_mut().access(|resolver| { - for cnum in resolver.cstore().crates_untracked() { - let source = resolver.cstore().crate_source_untracked(cnum); - if let Some((path, _)) = &source.dylib { - files.push(escape_dep_filename(&path.display().to_string())); - } - if let Some((path, _)) = &source.rlib { - files.push(escape_dep_filename(&path.display().to_string())); - } - if let Some((path, _)) = &source.rmeta { - files.push(escape_dep_filename(&path.display().to_string())); - } + let cstore = cstore.as_any().downcast_ref::<CStore>().unwrap(); + for cnum in cstore.crates_untracked() { + let source = cstore.crate_source_untracked(cnum); + if let Some((path, _)) = &source.dylib { + files.push(escape_dep_filename(&path.display().to_string())); + } + if let Some((path, _)) = &source.rlib { + files.push(escape_dep_filename(&path.display().to_string())); } - }); + if let Some((path, _)) = &source.rmeta { + files.push(escape_dep_filename(&path.display().to_string())); + } + } } let mut file = BufWriter::new(fs::File::create(&deps_filename)?); @@ -620,7 +516,7 @@ fn write_out_deps( // prevents `make` from spitting out an error if a file is later // deleted. For more info see #28735 for path in files { - writeln!(file, "{}:", path)?; + writeln!(file, "{path}:")?; } // Emit special comments with information about accessed environment variables. @@ -633,16 +529,14 @@ fn write_out_deps( envs.sort_unstable(); writeln!(file)?; for (k, v) in envs { - write!(file, "# env-dep:{}", k)?; + write!(file, "# env-dep:{k}")?; if let Some(v) = v { - write!(file, "={}", v)?; + write!(file, "={v}")?; } writeln!(file)?; } } - - Ok(()) - })(); + }; match result { Ok(_) => { @@ -653,76 +547,88 @@ fn write_out_deps( } } Err(error) => { - sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error }); + sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error }); } } } -pub fn prepare_outputs( - sess: &Session, - compiler: &Compiler, - krate: &ast::Crate, - boxed_resolver: &RefCell<BoxedResolver>, - crate_name: &str, -) -> Result<OutputFilenames> { +fn resolver_for_lowering<'tcx>( + tcx: TyCtxt<'tcx>, + (): (), +) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> { + let arenas = Resolver::arenas(); + let krate = tcx.crate_for_resolver(()).steal(); + let mut resolver = Resolver::new(tcx, &krate, &arenas); + let krate = configure_and_expand(krate, &mut resolver); + + // Make sure we don't mutate the cstore from here on. + tcx.untracked().cstore.leak(); + + let ty::ResolverOutputs { + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver.into_outputs(); + + let feed = tcx.feed_unit_query(); + feed.resolutions(tcx.arena.alloc(untracked_resolutions)); + tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) +} + +fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> { + let sess = tcx.sess; let _timer = sess.timer("prepare_outputs"); + let (_, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let crate_name = tcx.crate_name(LOCAL_CRATE); // FIXME: rustdoc passes &[] instead of &krate.attrs here - let outputs = util::build_output_filenames( - &compiler.input, - &compiler.output_dir, - &compiler.output_file, - &compiler.temps_dir, - &krate.attrs, - sess, - ); + let outputs = util::build_output_filenames(&krate.attrs, sess); let output_paths = - generated_output_paths(sess, &outputs, compiler.output_file.is_some(), crate_name); + generated_output_paths(sess, &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) = compiler.input_path { + if let Some(ref input_path) = sess.io.input.opt_path() { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { - let reported = sess.emit_err(InputFileWouldBeOverWritten { path: input_path }); - return Err(reported); + sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path }); } if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) { - let reported = - sess.emit_err(GeneratedFileConflictsWithDirectory { input_path, dir_path }); - return Err(reported); + sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory { + input_path, + dir_path, + }); } } } - if let Some(ref dir) = compiler.temps_dir { + if let Some(ref dir) = sess.io.temps_dir { if fs::create_dir_all(dir).is_err() { - let reported = sess.emit_err(TempsDirError); - return Err(reported); + sess.emit_fatal(errors::TempsDirError); } } - write_out_deps(sess, boxed_resolver, &outputs, &output_paths); + write_out_deps(sess, &*tcx.cstore_untracked(), &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1; if !only_dep_info { - if let Some(ref dir) = compiler.output_dir { + if let Some(ref dir) = sess.io.output_dir { if fs::create_dir_all(dir).is_err() { - let reported = sess.emit_err(OutDirError); - return Err(reported); + sess.emit_fatal(errors::OutDirError); } } } - Ok(outputs) + outputs.into() } pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; + providers.output_filenames = output_filenames; + providers.resolver_for_lowering = resolver_for_lowering; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -752,40 +658,21 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock: extern_providers }); -pub struct QueryContext<'tcx> { - gcx: &'tcx GlobalCtxt<'tcx>, -} - -impl<'tcx> QueryContext<'tcx> { - pub fn enter<F, R>(&mut self, f: F) -> R - where - F: FnOnce(TyCtxt<'tcx>) -> R, - { - let icx = ty::tls::ImplicitCtxt::new(self.gcx); - ty::tls::enter_context(&icx, |_| f(icx.tcx)) - } -} - pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc<LintStore>, - krate: Lrc<ast::Crate>, dep_graph: DepGraph, - resolver: Rc<RefCell<BoxedResolver>>, - outputs: OutputFilenames, - crate_name: &str, + untracked: Untracked, queries: &'tcx OnceCell<TcxQueries<'tcx>>, - global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>, + gcx_cell: &'tcx OnceCell<GlobalCtxt<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>, -) -> QueryContext<'tcx> { +) -> &'tcx GlobalCtxt<'tcx> { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to // incr. comp. yet. dep_graph.assert_ignored(); - 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); @@ -804,26 +691,21 @@ pub fn create_global_ctxt<'tcx>( TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache) }); - let gcx = sess.time("setup_global_ctxt", || { - global_ctxt.get_or_init(move || { + sess.time("setup_global_ctxt", || { + gcx_cell.get_or_init(move || { TyCtxt::create_global_ctxt( sess, lint_store, arena, hir_arena, - resolver_outputs, - krate, + untracked, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), rustc_query_impl::query_callbacks(arena), - crate_name, - outputs, ) }) - }); - - QueryContext { gcx } + }) } /// Runs the resolution, type-checking, region checking and other @@ -913,6 +795,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { } }); + if tcx.sess.opts.unstable_opts.drop_tracking_mir { + tcx.hir().par_body_owners(|def_id| { + if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) { + tcx.ensure().mir_generator_witnesses(def_id); + tcx.ensure().check_generator_obligations(def_id); + } + }); + } + sess.time("layout_testing", || layout_test::test_layout(tcx)); // Avoid overwhelming user with errors if borrow checking failed. @@ -968,12 +859,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { pub fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, - outputs: &OutputFilenames, ) -> Box<dyn Any> { info!("Pre-codegen\n{:?}", tcx.debug_stats()); - let (metadata, need_metadata_module) = - rustc_metadata::fs::encode_and_write_metadata(tcx, outputs); + let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx); let codegen = tcx.sess.time("codegen_crate", move || { codegen_backend.codegen_crate(tcx, metadata, need_metadata_module) @@ -989,8 +878,8 @@ pub fn start_codegen<'tcx>( info!("Post-codegen\n{:?}", tcx.debug_stats()); if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { - if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) { - tcx.sess.emit_err(CantEmitMIR { error }); + if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { + tcx.sess.emit_err(errors::CantEmitMIR { error }); tcx.sess.abort_if_errors(); } } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 91d180e1eb7..a96cc95a384 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -1,63 +1,74 @@ use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation}; use crate::interface::{Compiler, Result}; -use crate::passes::{self, BoxedResolver, QueryContext}; +use crate::passes; 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::{Lrc, OnceCell, WorkerLocal}; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_data_structures::sync::{AppendOnlyVec, Lrc, OnceCell, RwLock, WorkerLocal}; +use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; +use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_query_impl::Queries as TcxQueries; use rustc_session::config::{self, OutputFilenames, OutputType}; +use rustc_session::cstore::Untracked; use rustc_session::{output::find_crate_name, Session}; use rustc_span::symbol::sym; +use rustc_span::Symbol; use std::any::Any; -use std::cell::{Ref, RefCell, RefMut}; -use std::rc::Rc; +use std::cell::{RefCell, RefMut}; +use std::sync::Arc; /// Represent the result of a query. /// -/// This result can be stolen with the [`take`] method and generated with the [`compute`] method. +/// This result can be stolen once with the [`steal`] method and generated with the [`compute`] method. /// -/// [`take`]: Self::take +/// [`steal`]: Steal::steal /// [`compute`]: Self::compute pub struct Query<T> { - result: RefCell<Option<Result<T>>>, + /// `None` means no value has been computed yet. + result: RefCell<Option<Result<Steal<T>>>>, } impl<T> Query<T> { - fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<&Query<T>> { - let mut result = self.result.borrow_mut(); - if result.is_none() { - *result = Some(f()); - } - result.as_ref().unwrap().as_ref().map(|_| self).map_err(|err| *err) + fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<QueryResult<'_, T>> { + RefMut::filter_map( + self.result.borrow_mut(), + |r: &mut Option<Result<Steal<T>>>| -> Option<&mut Steal<T>> { + r.get_or_insert_with(|| f().map(Steal::new)).as_mut().ok() + }, + ) + .map_err(|r| *r.as_ref().unwrap().as_ref().map(|_| ()).unwrap_err()) + .map(QueryResult) } +} + +pub struct QueryResult<'a, T>(RefMut<'a, Steal<T>>); + +impl<'a, T> std::ops::Deref for QueryResult<'a, T> { + type Target = RefMut<'a, Steal<T>>; - /// Takes ownership of the query result. Further attempts to take or peek the query - /// result will panic unless it is generated by calling the `compute` method. - pub fn take(&self) -> T { - self.result.borrow_mut().take().expect("missing query result").unwrap() + fn deref(&self) -> &Self::Target { + &self.0 } +} - /// Borrows the query result using the RefCell. Panics if the result is stolen. - pub fn peek(&self) -> Ref<'_, T> { - Ref::map(self.result.borrow(), |r| { - r.as_ref().unwrap().as_ref().expect("missing query result") - }) +impl<'a, T> std::ops::DerefMut for QueryResult<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 } +} - /// Mutably borrows the query result using the RefCell. Panics if the result is stolen. - pub fn peek_mut(&self) -> RefMut<'_, T> { - RefMut::map(self.result.borrow_mut(), |r| { - r.as_mut().unwrap().as_mut().expect("missing query result") - }) +impl<'a, 'tcx> QueryResult<'a, &'tcx GlobalCtxt<'tcx>> { + pub fn enter<T>(&mut self, f: impl FnOnce(TyCtxt<'tcx>) -> T) -> T { + (*self.0).get_mut().enter(f) } } @@ -69,7 +80,7 @@ impl<T> Default for Query<T> { pub struct Queries<'tcx> { compiler: &'tcx Compiler, - gcx: OnceCell<GlobalCtxt<'tcx>>, + gcx_cell: OnceCell<GlobalCtxt<'tcx>>, queries: OnceCell<TcxQueries<'tcx>>, arena: WorkerLocal<Arena<'tcx>>, @@ -77,12 +88,11 @@ pub struct Queries<'tcx> { dep_graph_future: Query<Option<DepGraphFuture>>, parse: Query<ast::Crate>, - crate_name: Query<String>, + crate_name: Query<Symbol>, register_plugins: Query<(ast::Crate, Lrc<LintStore>)>, - expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>, dep_graph: Query<DepGraph>, - prepare_outputs: Query<OutputFilenames>, - global_ctxt: Query<QueryContext<'tcx>>, + // This just points to what's in `gcx_cell`. + gcx: Query<&'tcx GlobalCtxt<'tcx>>, ongoing_codegen: Query<Box<dyn Any>>, } @@ -90,7 +100,7 @@ impl<'tcx> Queries<'tcx> { pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> { Queries { compiler, - gcx: OnceCell::new(), + gcx_cell: OnceCell::new(), queries: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), @@ -98,10 +108,8 @@ impl<'tcx> Queries<'tcx> { parse: Default::default(), crate_name: Default::default(), register_plugins: Default::default(), - expansion: Default::default(), dep_graph: Default::default(), - prepare_outputs: Default::default(), - global_ctxt: Default::default(), + gcx: Default::default(), ongoing_codegen: Default::default(), } } @@ -113,24 +121,22 @@ impl<'tcx> Queries<'tcx> { self.compiler.codegen_backend() } - fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> { + fn dep_graph_future(&self) -> Result<QueryResult<'_, Option<DepGraphFuture>>> { self.dep_graph_future.compute(|| { let sess = self.session(); Ok(sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess))) }) } - pub fn parse(&self) -> Result<&Query<ast::Crate>> { - self.parse.compute(|| { - passes::parse(self.session(), &self.compiler.input) - .map_err(|mut parse_error| parse_error.emit()) - }) + pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> { + self.parse + .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit())) } - pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> { + pub fn register_plugins(&self) -> Result<QueryResult<'_, (ast::Crate, Lrc<LintStore>)>> { self.register_plugins.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); - let krate = self.parse()?.take(); + let crate_name = *self.crate_name()?.borrow(); + let krate = self.parse()?.steal(); let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {}; let (krate, lint_store) = passes::register_plugins( @@ -138,7 +144,7 @@ impl<'tcx> Queries<'tcx> { &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_deref().unwrap_or_else(|| empty), krate, - &crate_name, + crate_name, )?; // Compute the dependency graph (in the background). We want to do @@ -152,43 +158,21 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn crate_name(&self) -> Result<&Query<String>> { + fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> { self.crate_name.compute(|| { Ok({ let parse_result = self.parse()?; - let krate = parse_result.peek(); + let krate = parse_result.borrow(); // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. - find_crate_name(self.session(), &krate.attrs, &self.compiler.input) + find_crate_name(self.session(), &krate.attrs) }) }) } - pub fn expansion( - &self, - ) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> { - trace!("expansion"); - self.expansion.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); - let (krate, lint_store) = self.register_plugins()?.take(); - let _timer = self.session().timer("configure_and_expand"); - let sess = self.session(); - let mut resolver = passes::create_resolver( - sess.clone(), - self.codegen_backend().metadata_loader(), - &krate, - &crate_name, - ); - let krate = resolver.access(|resolver| { - passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) - })?; - Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) - }) - } - - fn dep_graph(&self) -> Result<&Query<DepGraph>> { + fn dep_graph(&self) -> Result<QueryResult<'_, DepGraph>> { self.dep_graph.compute(|| { let sess = self.session(); - let future_opt = self.dep_graph_future()?.take(); + let future_opt = self.dep_graph_future()?.steal(); let dep_graph = future_opt .and_then(|future| { let (prev_graph, prev_work_products) = @@ -201,46 +185,49 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> { - self.prepare_outputs.compute(|| { - let (krate, boxed_resolver, _) = &*self.expansion()?.peek(); - let crate_name = self.crate_name()?.peek(); - passes::prepare_outputs( - self.session(), - self.compiler, - krate, - &*boxed_resolver, - &crate_name, - ) - }) - } + pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { + self.gcx.compute(|| { + let crate_name = *self.crate_name()?.borrow(); + let (krate, lint_store) = self.register_plugins()?.steal(); - pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> { - self.global_ctxt.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); - let outputs = self.prepare_outputs()?.peek().clone(); - let dep_graph = self.dep_graph()?.peek().clone(); - let (krate, resolver, lint_store) = self.expansion()?.take(); - Ok(passes::create_global_ctxt( + let sess = self.session(); + + let cstore = RwLock::new(Box::new(CStore::new(sess)) as _); + let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id())); + let source_span = AppendOnlyVec::new(); + let _id = source_span.push(krate.spans.inner_span); + debug_assert_eq!(_id, CRATE_DEF_ID); + let untracked = Untracked { cstore, source_span, definitions }; + + let qcx = passes::create_global_ctxt( self.compiler, lint_store, - krate, - dep_graph, - resolver, - outputs, - &crate_name, + self.dep_graph()?.steal(), + untracked, &self.queries, - &self.gcx, + &self.gcx_cell, &self.arena, &self.hir_arena, - )) + ); + + qcx.enter(|tcx| { + let feed = tcx.feed_local_crate(); + feed.crate_name(crate_name); + + let feed = tcx.feed_unit_query(); + feed.crate_for_resolver(tcx.arena.alloc(Steal::new(krate))); + feed.metadata_loader( + tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())), + ); + feed.features_query(tcx.sess.features_untracked()); + }); + Ok(qcx) }) } - pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> { + pub fn ongoing_codegen(&'tcx self) -> Result<QueryResult<'_, Box<dyn Any>>> { self.ongoing_codegen.compute(|| { - let outputs = self.prepare_outputs()?; - self.global_ctxt()?.peek_mut().enter(|tcx| { + self.global_ctxt()?.enter(|tcx| { tcx.analysis(()).ok(); // Don't do code generation if there were any errors @@ -253,7 +240,7 @@ impl<'tcx> Queries<'tcx> { // Hook for UI tests. Self::check_for_rustc_errors_attr(tcx); - Ok(passes::start_codegen(&***self.codegen_backend(), tcx, &*outputs.peek())) + Ok(passes::start_codegen(&***self.codegen_backend(), tcx)) }) }) } @@ -296,10 +283,10 @@ impl<'tcx> Queries<'tcx> { let sess = self.session().clone(); let codegen_backend = self.codegen_backend().clone(); - let dep_graph = self.dep_graph()?.peek().clone(); - let prepare_outputs = self.prepare_outputs()?.take(); - let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE)); - let ongoing_codegen = self.ongoing_codegen()?.take(); + let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| { + (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone(), tcx.dep_graph.clone()) + }); + let ongoing_codegen = self.ongoing_codegen()?.steal(); Ok(Linker { sess, @@ -320,7 +307,7 @@ pub struct Linker { // compilation outputs dep_graph: DepGraph, - prepare_outputs: OutputFilenames, + prepare_outputs: Arc<OutputFilenames>, crate_hash: Svh, ongoing_codegen: Box<dyn Any>, } @@ -382,7 +369,8 @@ impl Compiler { // NOTE: intentionally does not compute the global context if it hasn't been built yet, // since that likely means there was a parse error. - if let Some(Ok(gcx)) = &mut *queries.global_ctxt.result.borrow_mut() { + if let Some(Ok(gcx)) = &mut *queries.gcx.result.borrow_mut() { + let gcx = gcx.get_mut(); // We assume that no queries are run past here. If there are new queries // after this point, they'll show up as "<unknown>" in self-profiling data. { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a03e7b0dae5..18d84a7023a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -3,29 +3,32 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; -use rustc_session::config::InstrumentCoverage; -use rustc_session::config::Strip; +use rustc_session::config::rustc_optgroups; +use rustc_session::config::Input; +use rustc_session::config::InstrumentXRay; +use rustc_session::config::TraitSolver; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; use rustc_session::config::{ - rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes, -}; -use rustc_session::config::{ BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet, ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel, }; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; +use rustc_session::config::{DumpMonoStatsFormat, MirSpanview}; +use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip}; +use rustc_session::config::{InstrumentCoverage, Passes}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; +use rustc_session::CompilerIO; use rustc_session::{build_session, getopts, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; +use rustc_span::FileName; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; -use std::iter::FromIterator; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; @@ -40,7 +43,14 @@ 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, Default::default(), None, None); + 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() }, + output_dir: None, + output_file: None, + temps_dir, + }; + let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None); (sess, cfg) } @@ -648,12 +658,14 @@ 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!(dump_mir_spanview, Some(MirSpanview::Statement)); + untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); + untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json); untracked!(dylib_lto, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); untracked!(hir_stats, true); untracked!(identify_regions, true); - untracked!(incremental_ignore_spans, true); untracked!(incremental_info, true); untracked!(incremental_verify_ich, true); untracked!(input_stats, true); @@ -666,7 +678,6 @@ fn test_unstable_options_tracking_hash() { untracked!(mir_pretty_relative_line_numbers, true); untracked!(nll_facts, true); untracked!(no_analysis, true); - untracked!(no_interleave_lints, true); untracked!(no_leak_check, true); untracked!(no_parallel_llvm, true); untracked!(parse_only, true); @@ -680,7 +691,6 @@ fn test_unstable_options_tracking_hash() { 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)); untracked!(self_profile_events, Some(vec![String::new()])); untracked!(span_debug, true); @@ -715,7 +725,7 @@ fn test_unstable_options_tracking_hash() { tracked!(asm_comments, true); tracked!(assume_incomplete_release, true); tracked!(binary_dep_depinfo, true); - tracked!(box_noalias, Some(false)); + tracked!(box_noalias, false); tracked!( branch_protection, Some(BranchProtection { @@ -723,7 +733,6 @@ fn test_unstable_options_tracking_hash() { pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B }) }) ); - tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(debug_info_for_profiling, true); @@ -739,22 +748,27 @@ fn test_unstable_options_tracking_hash() { tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); + tracked!(incremental_ignore_spans, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); tracked!(inline_mir_hint_threshold, Some(123)); tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); + tracked!(instrument_xray, Some(InstrumentXRay::default())); + tracked!(link_directives, false); tracked!(link_only, true); 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); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); - tracked!(mutable_noalias, Some(true)); + tracked!(mutable_noalias, false); tracked!(no_generate_arange_section, true); + tracked!(no_jump_tables, true); tracked!(no_link, true); tracked!(no_profiler_runtime, true); tracked!(no_unique_section_names, true); @@ -763,7 +777,6 @@ fn test_unstable_options_tracking_hash() { tracked!(packed_bundled_libs, true); tracked!(panic_abort_tests, true); tracked!(panic_in_drop, PanicStrategy::Abort); - tracked!(pick_stable_methods_before_any_unstable, false); tracked!(plt, Some(true)); tracked!(polonius, true); tracked!(precise_enum_drop_elaboration, false); @@ -789,7 +802,9 @@ fn test_unstable_options_tracking_hash() { tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); + tracked!(tiny_const_eval_limit, true); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); + tracked!(trait_solver, TraitSolver::Chalk); tracked!(translate_remapped_path_to_local_path, false); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 2fe3fb2fa56..e5d2fb2ea28 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,3 +1,4 @@ +use crate::errors; use info; use libloading::Library; use rustc_ast as ast; @@ -8,15 +9,16 @@ use rustc_parse::validate_attr; 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::config::{ErrorOutputType, OutputFilenames}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; use rustc_session::{early_error, filesearch, output, Session}; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; +use session::CompilerIO; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::mem; @@ -57,8 +59,9 @@ pub fn create_session( sopts: config::Options, cfg: FxHashSet<(String, Option<String>)>, check_cfg: CheckCfg, + locale_resources: &'static [&'static str], file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>, - input_path: Option<PathBuf>, + io: CompilerIO, lint_caps: FxHashMap<lint::LintId, lint::Level>, make_codegen_backend: Option< Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>, @@ -68,10 +71,7 @@ pub fn create_session( let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { make_codegen_backend(&sopts) } else { - get_codegen_backend( - &sopts.maybe_sysroot, - sopts.unstable_opts.codegen_backend.as_ref().map(|name| &name[..]), - ) + get_codegen_backend(&sopts.maybe_sysroot, sopts.unstable_opts.codegen_backend.as_deref()) }; // target_override is documented to be called before init(), so this is okay @@ -90,11 +90,15 @@ pub fn create_session( } }; + let mut locale_resources = Vec::from(locale_resources); + locale_resources.push(codegen_backend.locale_resource()); + let mut sess = session::build_session( sopts, - input_path, + io, bundle, descriptions, + locale_resources, lint_caps, file_loader, target_override, @@ -208,13 +212,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {:?}: {}", path, err); + let err = format!("couldn't load codegen backend {path:?}: {err}"); early_error(ErrorOutputType::default(), &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); + let err = format!("couldn't load codegen backend: {e}"); early_error(ErrorOutputType::default(), &err); }); @@ -260,7 +264,7 @@ pub fn rustc_path<'a>() -> Option<&'a Path> { const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR"); - RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_ref().map(|v| &**v) + RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_deref() } fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> { @@ -307,8 +311,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M .join("\n* "); let err = format!( "failed to find a `codegen-backends` folder \ - in the sysroot candidates:\n* {}", - candidates + in the sysroot candidates:\n* {candidates}" ); early_error(ErrorOutputType::default(), &err); }); @@ -328,7 +331,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M let expected_names = &[ format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")), - format!("rustc_codegen_{}", backend_name), + format!("rustc_codegen_{backend_name}"), ]; for entry in d.filter_map(|e| e.ok()) { let path = entry.path(); @@ -357,7 +360,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M match file { Some(ref s) => load_backend_from_dylib(s), None => { - let err = format!("unsupported builtin codegen backend `{}`", backend_name); + let err = format!("unsupported builtin codegen backend `{backend_name}`"); early_error(ErrorOutputType::default(), &err); } } @@ -392,7 +395,7 @@ pub(crate) fn check_attr_crate_type( BuiltinLintDiagnostics::UnknownCrateTypes( span, "did you mean".to_string(), - format!("\"{}\"", candidate), + format!("\"{candidate}\""), ), ); } else { @@ -475,35 +478,27 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C } base.retain(|crate_type| { - let res = !output::invalid_output_for_target(session, *crate_type); - - if !res { - session.warn(&format!( - "dropping unsupported crate type `{}` for target `{}`", - *crate_type, session.opts.target_triple - )); + if output::invalid_output_for_target(session, *crate_type) { + session.emit_warning(errors::UnsupportedCrateTypeForTarget { + crate_type: *crate_type, + target_triple: &session.opts.target_triple, + }); + false + } else { + true } - - res }); base } -pub fn build_output_filenames( - input: &Input, - odir: &Option<PathBuf>, - ofile: &Option<PathBuf>, - temps_dir: &Option<PathBuf>, - attrs: &[ast::Attribute], - sess: &Session, -) -> OutputFilenames { - match *ofile { +pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> OutputFilenames { + match sess.io.output_file { None => { // "-" as input file will cause the parser to read from stdin so we // have to make up a name // We want to toss everything after the final '.' - let dirpath = (*odir).as_ref().cloned().unwrap_or_default(); + let dirpath = sess.io.output_dir.clone().unwrap_or_default(); // If a crate name is present, we use it as the link name let stem = sess @@ -511,13 +506,13 @@ pub fn build_output_filenames( .crate_name .clone() .or_else(|| rustc_attr::find_crate_name(sess, attrs).map(|n| n.to_string())) - .unwrap_or_else(|| input.filestem().to_owned()); + .unwrap_or_else(|| sess.io.input.filestem().to_owned()); OutputFilenames::new( dirpath, stem, None, - temps_dir.clone(), + sess.io.temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -527,26 +522,23 @@ pub fn build_output_filenames( let unnamed_output_types = sess.opts.output_types.values().filter(|a| a.is_none()).count(); let ofile = if unnamed_output_types > 1 { - sess.warn( - "due to multiple output types requested, the explicitly specified \ - output file name will be adapted for each output type", - ); + sess.emit_warning(errors::MultipleOutputTypesAdaption); None } else { if !sess.opts.cg.extra_filename.is_empty() { - sess.warn("ignoring -C extra-filename flag due to -o flag"); + sess.emit_warning(errors::IgnoringExtraFilename); } Some(out_file.clone()) }; - if *odir != None { - sess.warn("ignoring --out-dir flag due to -o flag"); + if sess.io.output_dir != None { + sess.emit_warning(errors::IgnoringOutDir); } OutputFilenames::new( out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(), out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(), ofile, - temps_dir.clone(), + sess.io.temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) |
