diff options
Diffstat (limited to 'compiler/rustc_interface/src')
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 50 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 42 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/queries.rs | 83 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 7 |
4 files changed, 80 insertions, 102 deletions
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3920d3077d3..07ae24ee6d3 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -5,9 +5,9 @@ use std::sync::Arc; use rustc_ast::{LitKind, MetaItemKind, token}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::jobserver; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::{defer, jobserver}; use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; @@ -441,7 +441,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se temps_dir, }, bundle, - config.registry.clone(), + config.registry, locale_resources, config.lint_caps, target, @@ -492,32 +492,34 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se // There are two paths out of `f`. // - Normal exit. - // - Panic, e.g. triggered by `abort_if_errors`. + // - Panic, e.g. triggered by `abort_if_errors` or a fatal error. // // We must run `finish_diagnostics` in both cases. - let res = { - // If `f` panics, `finish_diagnostics` will run during - // unwinding because of the `defer`. - let sess_abort_guard = defer(|| { - compiler.sess.finish_diagnostics(&config.registry); - }); - - let res = f(&compiler); - - // If `f` doesn't panic, `finish_diagnostics` will run - // normally when `sess_abort_guard` is dropped. - drop(sess_abort_guard); - - // If error diagnostics have been emitted, we can't return an - // error directly, because the return type of this function - // is `R`, not `Result<R, E>`. But we need to communicate the - // errors' existence to the caller, otherwise the caller might - // mistakenly think that no errors occurred and return a zero - // exit code. So we abort (panic) instead, similar to if `f` - // had panicked. + let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&compiler))); + + compiler.sess.finish_diagnostics(); + + // If error diagnostics have been emitted, we can't return an + // error directly, because the return type of this function + // is `R`, not `Result<R, E>`. But we need to communicate the + // errors' existence to the caller, otherwise the caller might + // mistakenly think that no errors occurred and return a zero + // exit code. So we abort (panic) instead, similar to if `f` + // had panicked. + if res.is_ok() { compiler.sess.dcx().abort_if_errors(); + } + + // Also make sure to flush delayed bugs as if we panicked, the + // bugs would be flushed by the Drop impl of DiagCtxt while + // unwinding, which would result in an abort with + // "panic in a destructor during cleanup". + compiler.sess.dcx().flush_delayed(); - res + let res = match res { + Ok(res) => res, + // Resume unwinding if a panic happened. + Err(err) => std::panic::resume_unwind(err), }; let prof = compiler.sess.prof.clone(); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 43a98782016..62f35333015 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -33,15 +33,15 @@ use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_ use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{Symbol, sym}; -use rustc_span::{FileName, SourceFileHash, SourceFileHashAlgorithm}; +use rustc_span::{ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm}; use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; use tracing::{info, instrument}; -use crate::interface::{Compiler, Result}; +use crate::interface::Compiler; use crate::{errors, proc_macro_decls, util}; -pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> { +pub(crate) fn parse<'a>(sess: &'a Session) -> ast::Crate { let krate = sess .time("parse_crate", || { let mut parser = unwrap_or_emit_fatal(match &sess.io.input { @@ -52,17 +52,16 @@ pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> { }); parser.parse_crate_mod() }) - .map_err(|parse_error| parse_error.emit())?; - - if let Some(ref s) = sess.opts.unstable_opts.show_span { - rustc_ast_passes::show_span::run(sess.dcx(), s, &krate); - } + .unwrap_or_else(|parse_error| { + let guar: ErrorGuaranteed = parse_error.emit(); + guar.raise_fatal(); + }); if sess.opts.unstable_opts.input_stats { input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1"); } - Ok(krate) + krate } fn pre_expansion_lint<'a>( @@ -689,10 +688,12 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); rustc_borrowck::provide(providers); + rustc_incremental::provide(providers); rustc_mir_build::provide(providers); rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); + rustc_query_impl::provide(providers); rustc_resolve::provide(providers); rustc_hir_analysis::provide(providers); rustc_hir_typeck::provide(providers); @@ -714,7 +715,7 @@ pub(crate) fn create_global_ctxt<'tcx>( gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>, -) -> Result<&'tcx GlobalCtxt<'tcx>> { +) -> &'tcx GlobalCtxt<'tcx> { let sess = &compiler.sess; rustc_builtin_macros::cmdline_attrs::inject( @@ -735,7 +736,7 @@ pub(crate) fn create_global_ctxt<'tcx>( sess.cfg_version, ); let outputs = util::build_output_filenames(&pre_configured_attrs, sess); - let dep_graph = setup_dep_graph(sess)?; + let dep_graph = setup_dep_graph(sess); let cstore = FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _); @@ -798,7 +799,7 @@ pub(crate) fn create_global_ctxt<'tcx>( feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); }); - Ok(qcx) + qcx }) } @@ -828,7 +829,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.ensure().check_mod_attrs(module); tcx.ensure().check_mod_naked_functions(module); tcx.ensure().check_mod_unstable_api_usage(module); - tcx.ensure().check_mod_const_bodies(module); }); }, { @@ -879,7 +879,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { || tcx.hir().body_const_context(def_id).is_some() { tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); - tcx.ensure().unused_generic_params(ty::InstanceKind::Item(def_id.to_def_id())); } } }); @@ -898,8 +897,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs // in MIR optimizations that may only be reachable through codegen, or other codepaths - // that requires the optimized/ctfe MIR, such as polymorphization, coroutine bodies, - // or evaluating consts. + // that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts. if tcx.sess.opts.unstable_opts.validate_mir { sess.time("ensuring_final_MIR_is_computable", || { tcx.hir().par_body_owners(|def_id| { @@ -911,7 +909,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { /// Runs the type-checking, region checking and other miscellaneous analysis /// passes on the crate. -fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { +fn analysis(tcx: TyCtxt<'_>, (): ()) { run_required_analyses(tcx); let sess = tcx.sess; @@ -925,7 +923,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // But we exclude lint errors from this, because lint errors are typically // less serious and we're more likely to want to continue (#87337). if let Some(guar) = sess.dcx().has_errors_excluding_lint_errors() { - return Err(guar); + guar.raise_fatal(); } sess.time("misc_checking_3", || { @@ -1053,8 +1051,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }) } } - - Ok(()) } /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used @@ -1096,12 +1092,12 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { pub(crate) fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, -) -> Result<Box<dyn Any>> { +) -> Box<dyn Any> { // Don't do code generation if there were any errors. Likewise if // there were any delayed bugs, because codegen will likely cause // more ICEs, obscuring the original problem. if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() { - return Err(guar); + guar.raise_fatal(); } // Hook for UI tests. @@ -1129,7 +1125,7 @@ pub(crate) fn start_codegen<'tcx>( } } - Ok(codegen) + codegen } fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index b6837ec764f..7e3a1332630 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -12,13 +12,12 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{GlobalCtxt, TyCtxt}; -use rustc_serialize::opaque::FileEncodeResult; use rustc_session::Session; use rustc_session::config::{self, OutputFilenames, OutputType}; use crate::errors::FailedWritingFile; -use crate::interface::{Compiler, Result}; -use crate::{errors, passes}; +use crate::interface::Compiler; +use crate::passes; /// Represent the result of a query. /// @@ -28,19 +27,17 @@ use crate::{errors, passes}; /// [`compute`]: Self::compute pub struct Query<T> { /// `None` means no value has been computed yet. - result: RefCell<Option<Result<Steal<T>>>>, + result: RefCell<Option<Steal<T>>>, } impl<T> Query<T> { - fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<QueryResult<'_, T>> { - RefMut::filter_map( + fn compute<F: FnOnce() -> T>(&self, f: F) -> QueryResult<'_, T> { + QueryResult(RefMut::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() + |r: &mut Option<Steal<T>>| -> &mut Steal<T> { + r.get_or_insert_with(|| Steal::new(f())) }, - ) - .map_err(|r| *r.as_ref().unwrap().as_ref().map(|_| ()).unwrap_err()) - .map(QueryResult) + )) } } @@ -62,7 +59,7 @@ impl<'a, T> std::ops::DerefMut for QueryResult<'a, T> { 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) + (*self.0).borrow().enter(f) } } @@ -90,17 +87,19 @@ impl<'tcx> Queries<'tcx> { } } - pub fn finish(&self) -> FileEncodeResult { - if let Some(gcx) = self.gcx_cell.get() { gcx.finish() } else { Ok(0) } + pub fn finish(&'tcx self) { + if let Some(gcx) = self.gcx_cell.get() { + gcx.finish(); + } } - pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> { + pub fn parse(&self) -> QueryResult<'_, ast::Crate> { self.parse.compute(|| passes::parse(&self.compiler.sess)) } - pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'tcx, &'tcx GlobalCtxt<'tcx>>> { + pub fn global_ctxt(&'tcx self) -> QueryResult<'tcx, &'tcx GlobalCtxt<'tcx>> { self.gcx.compute(|| { - let krate = self.parse()?.steal(); + let krate = self.parse().steal(); passes::create_global_ctxt( self.compiler, @@ -125,8 +124,8 @@ impl Linker { pub fn codegen_and_build_linker( tcx: TyCtxt<'_>, codegen_backend: &dyn CodegenBackend, - ) -> Result<Linker> { - let ongoing_codegen = passes::start_codegen(codegen_backend, tcx)?; + ) -> Linker { + let ongoing_codegen = passes::start_codegen(codegen_backend, tcx); // This must run after monomorphization so that all generic types // have been instantiated. @@ -140,7 +139,7 @@ impl Linker { tcx.sess.code_stats.print_vtable_sizes(crate_name); } - Ok(Linker { + Linker { dep_graph: tcx.dep_graph.clone(), output_filenames: Arc::clone(tcx.output_filenames(())), crate_hash: if tcx.needs_crate_hash() { @@ -149,16 +148,17 @@ impl Linker { None }, ongoing_codegen, - }) + } } - pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { - let (codegen_results, work_products) = - codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames); + pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) { + let (codegen_results, work_products) = sess.time("finish_ongoing_codegen", || { + codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames) + }); - if let Some(guar) = sess.dcx().has_errors() { - return Err(guar); - } + sess.dcx().abort_if_errors(); + + let _timer = sess.timer("link"); sess.time("serialize_work_products", || { rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products) @@ -177,7 +177,7 @@ impl Linker { .keys() .any(|&i| i == OutputType::Exe || i == OutputType::Metadata) { - return Ok(()); + return; } if sess.opts.unstable_opts.no_link { @@ -188,10 +188,10 @@ impl Linker { &codegen_results, &*self.output_filenames, ) - .map_err(|error| { + .unwrap_or_else(|error| { sess.dcx().emit_fatal(FailedWritingFile { path: &rlink_file, error }) - })?; - return Ok(()); + }); + return; } let _timer = sess.prof.verbose_generic_activity("link_crate"); @@ -209,29 +209,10 @@ impl Compiler { let queries = Queries::new(self); let ret = f(&queries); - // 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.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. - { - let _prof_timer = - queries.compiler.sess.prof.generic_activity("self_profile_alloc_query_strings"); - gcx.enter(rustc_query_impl::alloc_self_profile_query_strings); - } - - self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); - - gcx.enter(rustc_query_impl::query_key_hash_verify_all); - } - // The timer's lifetime spans the dropping of `queries`, which contains // the global context. _timer = self.sess.timer("free_global_ctxt"); - if let Err((path, error)) = queries.finish() { - self.sess.dcx().emit_fatal(errors::FailedWritingFile { path: &path, error }); - } + queries.finish(); ret } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index e48c4d46b59..e76e9ca9f85 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -712,7 +712,7 @@ fn test_unstable_options_tracking_hash() { untracked!(no_analysis, true); untracked!(no_leak_check, true); untracked!(no_parallel_backend, true); - untracked!(parse_only, true); + untracked!(parse_crate_root_only, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(print_codegen_stats, true); @@ -771,6 +771,7 @@ fn test_unstable_options_tracking_hash() { tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); + tracked!(debug_info_type_line_numbers, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); tracked!(dep_info_omit_d_target, true); tracked!(direct_access_external_data, Some(true)); @@ -784,7 +785,6 @@ fn test_unstable_options_tracking_hash() { tracked!(flatten_format_args, false); tracked!(fmt_debug, FmtDebug::Shallow); tracked!(force_unstable_if_unmarked, true); - tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_return, FunctionReturn::ThunkExtern); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); @@ -830,9 +830,9 @@ fn test_unstable_options_tracking_hash() { tracked!(plt, Some(true)); tracked!(polonius, Polonius::Legacy); tracked!(precise_enum_drop_elaboration, false); - tracked!(print_fuel, Some("abc".to_string())); tracked!(profile_sample_use, Some(PathBuf::from("abc"))); tracked!(profiler_runtime, "abc".to_string()); + tracked!(reg_struct_return, true); tracked!(regparm, Some(3)); tracked!(relax_elf_relocations, Some(true)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); @@ -845,7 +845,6 @@ fn test_unstable_options_tracking_hash() { tracked!(sanitizer_recover, SanitizerSet::ADDRESS); tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); - tracked!(show_span, Some(String::from("abc"))); tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(small_data_threshold, Some(16)); tracked!(split_lto_unit, Some(true)); |
