diff options
Diffstat (limited to 'compiler/rustc_interface')
-rw-r--r-- | compiler/rustc_interface/Cargo.toml | 1 | ||||
-rw-r--r-- | compiler/rustc_interface/src/callbacks.rs | 13 | ||||
-rw-r--r-- | compiler/rustc_interface/src/errors.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_interface/src/interface.rs | 51 | ||||
-rw-r--r-- | compiler/rustc_interface/src/lib.rs | 1 | ||||
-rw-r--r-- | compiler/rustc_interface/src/passes.rs | 71 | ||||
-rw-r--r-- | compiler/rustc_interface/src/queries.rs | 158 | ||||
-rw-r--r-- | compiler/rustc_interface/src/tests.rs | 36 | ||||
-rw-r--r-- | compiler/rustc_interface/src/util.rs | 41 |
9 files changed, 178 insertions, 198 deletions
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index e67dec31d..f817c5bc1 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -45,6 +45,7 @@ rustc_plugin_impl = { path = "../rustc_plugin_impl" } rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } rustc_resolve = { path = "../rustc_resolve" } +rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 76442de69..ee0552d77 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 f5135c78d..15d7e977b 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -87,3 +87,7 @@ pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } + +#[derive(Diagnostic)] +#[diag(interface_proc_macro_crate_panic_abort)] +pub struct ProcMacroCratePanicAbort; diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 4c22ab68a..7a5e45ada 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -14,10 +14,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 +35,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 +47,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 +55,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 +66,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 +125,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); @@ -246,7 +220,6 @@ 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>>, @@ -289,12 +262,19 @@ 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.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 +284,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_deref().map(PathBuf::from); - 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 542b638bb..82bc4770b 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)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f808c1438..379a76528 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,7 +1,8 @@ use crate::errors::{ CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, - MixedProcMacroCrate, OutDirError, ProcMacroDocWithoutArg, TempsDirError, + MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg, + TempsDirError, }; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; @@ -12,7 +13,6 @@ 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_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; @@ -30,12 +30,13 @@ use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; +use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn, 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; @@ -49,8 +50,8 @@ use std::rc::Rc; use std::sync::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) @@ -380,6 +381,10 @@ pub fn configure_and_expand( } } + if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { + sess.emit_warning(ProcMacroCratePanicAbort); + } + // For backwards compatibility, we don't try to run proc macro injection // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being // specified. This should only affect users who manually invoke 'rustdoc', as @@ -553,7 +558,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 @@ -620,7 +625,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 +638,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(_) => { @@ -660,7 +663,6 @@ fn write_out_deps( pub fn prepare_outputs( sess: &Session, - compiler: &Compiler, krate: &ast::Crate, boxed_resolver: &RefCell<BoxedResolver>, crate_name: Symbol, @@ -668,20 +670,13 @@ pub fn prepare_outputs( let _timer = sess.timer("prepare_outputs"); // 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 }); @@ -695,7 +690,7 @@ pub fn prepare_outputs( } } - 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); @@ -708,7 +703,7 @@ pub fn prepare_outputs( && 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); @@ -769,11 +764,8 @@ impl<'tcx> QueryContext<'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: Symbol, + untracked: Untracked, queries: &'tcx OnceCell<TcxQueries<'tcx>>, global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>, @@ -784,8 +776,6 @@ pub fn create_global_ctxt<'tcx>( // 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,12 +794,6 @@ pub fn create_global_ctxt<'tcx>( TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache) }); - let ty::ResolverOutputs { - definitions, - global_ctxt: untracked_resolutions, - ast_lowering: untracked_resolver_for_lowering, - } = resolver_outputs; - let gcx = sess.time("setup_global_ctxt", || { global_ctxt.get_or_init(move || { TyCtxt::create_global_ctxt( @@ -817,25 +801,16 @@ pub fn create_global_ctxt<'tcx>( lint_store, arena, hir_arena, - definitions, - untracked_resolutions, - 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, ) }) }); - let mut qcx = QueryContext { gcx }; - qcx.enter(|tcx| { - tcx.feed_unit_query() - .resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering))) - }); - qcx + QueryContext { gcx } } /// Runs the resolution, type-checking, region checking and other diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 39e1f2204..d5a49dd75 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -5,6 +5,7 @@ use crate::passes::{self, BoxedResolver, QueryContext}; 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; @@ -12,50 +13,60 @@ use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::ty::{GlobalCtxt, TyCtxt}; +use rustc_middle::ty::{self, GlobalCtxt, TyCtxt}; use rustc_query_impl::Queries as TcxQueries; use rustc_session::config::{self, OutputFilenames, OutputType}; 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::cell::{RefCell, RefMut}; use std::rc::Rc; 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>> { - self.result.borrow_mut().get_or_insert_with(f).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, QueryContext<'tcx>> { + pub fn enter<T>(mut self, f: impl FnOnce(TyCtxt<'tcx>) -> T) -> T { + (*self.0).get_mut().enter(f) } } @@ -79,7 +90,6 @@ pub struct Queries<'tcx> { 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>>, ongoing_codegen: Query<Box<dyn Any>>, } @@ -98,7 +108,6 @@ impl<'tcx> Queries<'tcx> { register_plugins: Default::default(), expansion: Default::default(), dep_graph: Default::default(), - prepare_outputs: Default::default(), global_ctxt: Default::default(), ongoing_codegen: Default::default(), } @@ -111,24 +120,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( @@ -150,24 +157,25 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn crate_name(&self) -> Result<&Query<Symbol>> { + 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>)>> { + ) -> Result<QueryResult<'_, (Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> + { trace!("expansion"); self.expansion.compute(|| { - let crate_name = *self.crate_name()?.peek(); - let (krate, lint_store) = self.register_plugins()?.take(); + let crate_name = *self.crate_name()?.borrow(); + let (krate, lint_store) = self.register_plugins()?.steal(); let _timer = self.session().timer("configure_and_expand"); let sess = self.session(); let mut resolver = passes::create_resolver( @@ -183,10 +191,10 @@ impl<'tcx> Queries<'tcx> { }) } - 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) = @@ -199,45 +207,48 @@ 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<&Query<QueryContext<'tcx>>> { + pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, QueryContext<'tcx>>> { self.global_ctxt.compute(|| { - let crate_name = *self.crate_name()?.peek(); - let outputs = self.prepare_outputs()?.take(); - let dep_graph = self.dep_graph()?.peek().clone(); - let (krate, resolver, lint_store) = self.expansion()?.take(); - Ok(passes::create_global_ctxt( + let crate_name = *self.crate_name()?.borrow(); + let (krate, resolver, lint_store) = self.expansion()?.steal(); + + let outputs = passes::prepare_outputs(self.session(), &krate, &resolver, crate_name)?; + + let ty::ResolverOutputs { + untracked, + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = BoxedResolver::to_resolver_outputs(resolver); + + let mut 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.arena, &self.hir_arena, - )) + ); + + qcx.enter(|tcx| { + let feed = tcx.feed_unit_query(); + feed.resolver_for_lowering( + tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, krate))), + ); + feed.resolutions(tcx.arena.alloc(untracked_resolutions)); + feed.output_filenames(tcx.arena.alloc(std::sync::Arc::new(outputs))); + feed.features_query(tcx.sess.features_untracked()); + let feed = tcx.feed_local_crate(); + feed.crate_name(crate_name); + }); + 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(|| { - 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 @@ -293,12 +304,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 (crate_hash, prepare_outputs) = self - .global_ctxt()? - .peek_mut() - .enter(|tcx| (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone())); - 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, @@ -382,6 +391,7 @@ 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() { + 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 2b8f6557c..f94bc4d4c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -3,29 +3,31 @@ 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::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 +42,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, Default::default(), None, None); (sess, cfg) } @@ -648,12 +657,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); @@ -714,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 { @@ -722,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); @@ -738,6 +748,7 @@ 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)); @@ -747,14 +758,16 @@ fn test_unstable_options_tracking_hash() { tracked!(link_only, true); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); + tracked!(log_backtrace, Some("filter".to_string())); 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); @@ -790,6 +803,7 @@ fn test_unstable_options_tracking_hash() { tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, 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 4142964a0..54363e07b 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -8,7 +8,7 @@ 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; @@ -17,6 +17,7 @@ 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; @@ -58,7 +59,7 @@ pub fn create_session( cfg: FxHashSet<(String, Option<String>)>, check_cfg: CheckCfg, 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>, @@ -89,7 +90,7 @@ pub fn create_session( let mut sess = session::build_session( sopts, - input_path, + io, bundle, descriptions, lint_caps, @@ -205,13 +206,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); }); @@ -304,8 +305,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); }); @@ -325,7 +325,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(); @@ -354,7 +354,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); } } @@ -389,7 +389,7 @@ pub(crate) fn check_attr_crate_type( BuiltinLintDiagnostics::UnknownCrateTypes( span, "did you mean".to_string(), - format!("\"{}\"", candidate), + format!("\"{candidate}\""), ), ); } else { @@ -487,20 +487,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C 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 @@ -508,13 +501,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(), ) @@ -535,7 +528,7 @@ pub fn build_output_filenames( } Some(out_file.clone()) }; - if *odir != None { + if sess.io.output_dir != None { sess.warn("ignoring --out-dir flag due to -o flag"); } @@ -543,7 +536,7 @@ pub fn build_output_filenames( 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(), ) |