From 1e16927ef37eb841d6a38b5e61438931d20c43fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 16 Feb 2024 10:35:53 +1100 Subject: [PATCH 1/9] Remove an out-of-date comment. --- compiler/rustc_errors/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 052d9b3a78376..64b88adedbb54 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1271,7 +1271,6 @@ impl DiagCtxtInner { fn emit_stashed_diagnostics(&mut self) { let has_errors = !self.err_guars.is_empty(); for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { - // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { if diag.is_lint.is_none() { self.stashed_err_count -= 1; From 203b4332bb3da3af092344b3459416aeab4c90ef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 16 Feb 2024 14:50:07 +1100 Subject: [PATCH 2/9] Remove dead `expect_error_or_delayed_bug` method. --- compiler/rustc_middle/src/ty/context.rs | 5 ----- compiler/rustc_type_ir/src/interner.rs | 3 --- 2 files changed, 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index cc734e7157fa4..9d59f779470f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -153,11 +153,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> Self::Const { Const::new_bound(self, debruijn, var, ty) } - - fn expect_error_or_delayed_bug() { - let has_errors = ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs()); - assert!(has_errors.is_some()); - } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 7728ee0e842a8..7d2c42a6dbe91 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -95,9 +95,6 @@ pub trait Interner: Sized { fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty; fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region; fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const; - - /// Assert that an error has been delayed or emitted. - fn expect_error_or_delayed_bug(); } /// Common capabilities of placeholder kinds From 9919c3dab3e4eabe466612de5f6c472e3e27ceb6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 16 Feb 2024 15:26:42 +1100 Subject: [PATCH 3/9] Remove `EarlyDiagCtxt::abort_if_errors`. Its one use isn't necessary, because it's not possible for errors to have been emitted at that point. --- compiler/rustc_driver_impl/src/lib.rs | 5 ++--- compiler/rustc_session/src/session.rs | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 60f11b1bdd490..9b2d760282f1c 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -349,11 +349,10 @@ fn run_compiler( }, }; - callbacks.config(&mut config); - - default_early_dcx.abort_if_errors(); drop(default_early_dcx); + callbacks.config(&mut config); + interface::run_compiler(config, |compiler| { let sess = &compiler.sess; let codegen_backend = &*compiler.codegen_backend; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 9d1133c487f65..422bbadf6a8a0 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1410,10 +1410,6 @@ impl EarlyDiagCtxt { Self { dcx: DiagCtxt::with_emitter(emitter) } } - pub fn abort_if_errors(&self) { - self.dcx.abort_if_errors() - } - /// Swap out the underlying dcx once we acquire the user's preference on error emission /// format. Any errors prior to that will cause an abort and all stashed diagnostics of the /// previous dcx will be emitted. From 46f49833566381887ba74e3f756271a6e8723636 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 19 Feb 2024 09:36:08 +1100 Subject: [PATCH 4/9] Adjust the `has_errors*` methods. Currently `has_errors` excludes lint errors. This commit changes it to include lint errors. The motivation for this is that for most places it doesn't matter whether lint errors are included or not. But there are multiple places where they must be includes, and only one place where they must not be included. So it makes sense for `has_errors` to do the thing that fits the most situations, and the new `has_errors_excluding_lint_errors` method in the one exceptional place. The same change is made for `err_count`. Annoyingly, this requires the introduction of `err_count_excluding_lint_errs` for one place, to preserve existing error printing behaviour. But I still think the change is worthwhile overall. --- compiler/rustc_errors/src/lib.rs | 46 +++++++++++-------- compiler/rustc_incremental/src/persist/fs.rs | 2 +- .../rustc_incremental/src/persist/save.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 9 ++-- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_metadata/src/creader.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 2 +- compiler/rustc_session/src/session.rs | 3 +- src/librustdoc/core.rs | 3 +- src/librustdoc/doctest.rs | 3 +- 10 files changed, 41 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 64b88adedbb54..a6b0a0e8f1751 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -754,13 +754,20 @@ impl DiagCtxt { self.inner.borrow_mut().emit_stashed_diagnostics() } - /// This excludes lint errors, delayed bugs, and stashed errors. + /// This excludes lint errors, delayed bugs and stashed errors. #[inline] - pub fn err_count(&self) -> usize { + pub fn err_count_excluding_lint_errs(&self) -> usize { self.inner.borrow().err_guars.len() } - /// This excludes normal errors, lint errors and delayed bugs. Unless + /// This excludes delayed bugs and stashed errors. + #[inline] + pub fn err_count(&self) -> usize { + let inner = self.inner.borrow(); + inner.err_guars.len() + inner.lint_err_guars.len() + } + + /// This excludes normal errors, lint errors, and delayed bugs. Unless /// absolutely necessary, avoid using this. It's dubious because stashed /// errors can later be cancelled, so the presence of a stashed error at /// some point of time doesn't guarantee anything -- there are no @@ -769,21 +776,21 @@ impl DiagCtxt { self.inner.borrow().stashed_err_count } - /// This excludes lint errors, delayed bugs, and stashed errors. - pub fn has_errors(&self) -> Option { - self.inner.borrow().has_errors() + /// This excludes lint errors, delayed bugs, and stashed errors. Unless + /// absolutely necessary, prefer `has_errors` to this method. + pub fn has_errors_excluding_lint_errors(&self) -> Option { + self.inner.borrow().has_errors_excluding_lint_errors() } - /// This excludes delayed bugs and stashed errors. Unless absolutely - /// necessary, prefer `has_errors` to this method. - pub fn has_errors_or_lint_errors(&self) -> Option { - self.inner.borrow().has_errors_or_lint_errors() + /// This excludes delayed bugs and stashed errors. + pub fn has_errors(&self) -> Option { + self.inner.borrow().has_errors() } /// This excludes stashed errors. Unless absolutely necessary, prefer - /// `has_errors` or `has_errors_or_lint_errors` to this method. - pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { - self.inner.borrow().has_errors_or_lint_errors_or_delayed_bugs() + /// `has_errors` to this method. + pub fn has_errors_or_delayed_bugs(&self) -> Option { + self.inner.borrow().has_errors_or_delayed_bugs() } pub fn print_error_count(&self, registry: &Registry) { @@ -1328,7 +1335,7 @@ impl DiagCtxtInner { DelayedBug => { // If we have already emitted at least one error, we don't need // to record the delayed bug, because it'll never be used. - return if let Some(guar) = self.has_errors_or_lint_errors() { + return if let Some(guar) = self.has_errors() { Some(guar) } else { let backtrace = std::backtrace::Backtrace::capture(); @@ -1444,17 +1451,16 @@ impl DiagCtxtInner { .is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get()) } - fn has_errors(&self) -> Option { + fn has_errors_excluding_lint_errors(&self) -> Option { self.err_guars.get(0).copied() } - fn has_errors_or_lint_errors(&self) -> Option { - self.has_errors().or_else(|| self.lint_err_guars.get(0).copied()) + fn has_errors(&self) -> Option { + self.has_errors_excluding_lint_errors().or_else(|| self.lint_err_guars.get(0).copied()) } - fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { - self.has_errors_or_lint_errors() - .or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) + fn has_errors_or_delayed_bugs(&self) -> Option { + self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`. diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 23d29916922ff..dd9c16d006a96 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -312,7 +312,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option) { let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone(); - if sess.dcx().has_errors_or_lint_errors_or_delayed_bugs().is_some() { + if sess.dcx().has_errors_or_delayed_bugs().is_some() { // If there have been any errors during compilation, we don't want to // publish this session directory. Rather, we'll just delete it. diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index ff0c58d09de2d..32759f5284af7 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -32,7 +32,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { return; } // This is going to be deleted in finalize_session_directory, so let's not create it. - if sess.dcx().has_errors_or_lint_errors_or_delayed_bugs().is_some() { + if sess.dcx().has_errors_or_delayed_bugs().is_some() { return; } @@ -87,7 +87,7 @@ pub fn save_work_product_index( return; } // This is going to be deleted in finalize_session_directory, so let's not create it - if sess.dcx().has_errors_or_lint_errors().is_some() { + if sess.dcx().has_errors().is_some() { return; } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 243558b11a863..f131d11c41159 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -713,7 +713,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_trait_errors: Default::default(), reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), - err_count_on_creation: tcx.dcx().err_count(), + err_count_on_creation: tcx.dcx().err_count_excluding_lint_errs(), stashed_err_count_on_creation: tcx.dcx().stashed_err_count(), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, @@ -1268,8 +1268,11 @@ impl<'tcx> InferCtxt<'tcx> { pub fn tainted_by_errors(&self) -> Option { if let Some(guar) = self.tainted_by_errors.get() { Some(guar) - } else if self.dcx().err_count() > self.err_count_on_creation { - // Errors reported since this infcx was made. + } else if self.dcx().err_count_excluding_lint_errs() > self.err_count_on_creation { + // Errors reported since this infcx was made. Lint errors are + // excluded to avoid some being swallowed in the presence of + // non-lint errors. (It's arguable whether or not this exclusion is + // important.) let guar = self.dcx().has_errors().unwrap(); self.set_tainted_by_errors(guar); Some(guar) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 60d13f02ad7b5..858db594b4773 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -772,7 +772,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // lot of annoying errors in the ui tests (basically, // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis - if let Some(reported) = sess.dcx().has_errors() { + if let Some(reported) = sess.dcx().has_errors_excluding_lint_errors() { return Err(reported); } else if sess.dcx().stashed_err_count() > 0 { // Without this case we sometimes get delayed bug ICEs and I don't diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f6d3dba247090..baa9af87a83c9 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -926,7 +926,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { what: &str, needs_dep: &dyn Fn(&CrateMetadata) -> bool, ) { - // don't perform this validation if the session has errors, as one of + // Don't perform this validation if the session has errors, as one of // those errors may indicate a circular dependency which could cause // this to stack overflow. if self.dcx().has_errors().is_some() { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index b6ac54a9ab59b..7dc1a1f791752 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -817,7 +817,7 @@ impl DepGraphData { None => {} } - if let None = qcx.dep_context().sess().dcx().has_errors_or_lint_errors_or_delayed_bugs() { + if let None = qcx.dep_context().sess().dcx().has_errors_or_delayed_bugs() { panic!("try_mark_previous_green() - Forcing the DepNode should have set its color") } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 422bbadf6a8a0..f8a1d79659d95 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -313,8 +313,7 @@ impl Session { } pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { - // We must include lint errors here. - if let Some(reported) = self.dcx().has_errors_or_lint_errors() { + if let Some(reported) = self.dcx().has_errors() { self.dcx().emit_stashed_diagnostics(); Err(reported) } else { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index efad5a8d808dd..3f7edd049a713 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -452,8 +452,7 @@ pub(crate) fn run_global_ctxt( tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc))); - // We must include lint errors here. - if tcx.dcx().has_errors_or_lint_errors().is_some() { + if tcx.dcx().has_errors().is_some() { rustc_errors::FatalError.raise(); } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f9d4d1af1140f..09a90b62d97be 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -153,8 +153,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { collector }); - // We must include lint errors here. - if compiler.sess.dcx().has_errors_or_lint_errors().is_some() { + if compiler.sess.dcx().has_errors().is_some() { FatalError.raise(); } From 72b172bdf631483d0f802c54c8dc8246f6b4e00e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 19 Feb 2024 10:00:19 +1100 Subject: [PATCH 5/9] Overhaul the handling of errors at the top-level. Currently `emit_stashed_diagnostic` is called from four(!) different places: `print_error_count`, `DiagCtxtInner::drop`, `abort_if_errors`, and `compile_status`. And `flush_delayed` is called from two different places: `DiagCtxtInner::drop` and `Queries`. This is pretty gross! Each one should really be called from a single place, but there's a bunch of entanglements. This commit cleans up this mess. Specifically, it: - Removes all the existing calls to `emit_stashed_diagnostic`, and adds a single new call in `finish_diagnostics`. - Removes the early `flush_delayed` call in `codegen_and_build_linker`, replacing it with a simple early return if delayed bugs are present. - Changes `DiagCtxtInner::drop` and `DiagCtxtInner::flush_delayed` so they both assert that the stashed diagnostics are empty (i.e. processed beforehand). - Changes `interface::run_compiler` so that any errors emitted during `finish_diagnostics` (i.e. late-emitted stashed diagnostics) are counted and cannot be overlooked. This requires adding `ErrorGuaranteed` return values to several functions. - Removes the `stashed_err_count` call in `analysis`. This is possible now that we don't have to worry about calling `flush_delayed` early from `codegen_and_build_linker` when stashed diagnostics are pending. - Changes the `span_bug` case in `handle_tuple_field_pattern_match` to a `delayed_span_bug`, because it now can be reached due to the removal of the `stashed_err_count` call in `analysis`. - Slightly changes the expected output of three tests. If no errors are emitted but there are delayed bugs, the error count is no longer printed. This is because delayed bugs are now always printed after the error count is printed (or not printed, if the error count is zero). There is a lot going on in this commit. It's hard to break into smaller pieces because the existing code is very tangled. It took me a long time and a lot of effort to understand how the different pieces interact, and I think the new code is a lot simpler and easier to understand. --- compiler/rustc_errors/src/lib.rs | 32 ++++++++++------ compiler/rustc_interface/src/interface.rs | 37 ++++++++++++++++--- compiler/rustc_interface/src/passes.rs | 11 +++--- compiler/rustc_interface/src/queries.rs | 12 +++--- compiler/rustc_passes/src/dead.rs | 5 ++- compiler/rustc_session/src/session.rs | 14 ++++--- .../equality-in-canonical-query.clone.stderr | 2 - .../ui/inference/issue-80409.no-compat.stderr | 2 - ...equality_in_canonical_query.current.stderr | 2 - 9 files changed, 76 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a6b0a0e8f1751..fafd636bb7091 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -471,9 +471,10 @@ struct DiagCtxtInner { emitted_diagnostics: FxHashSet, /// Stashed diagnostics emitted in one stage of the compiler that may be - /// stolen by other stages (e.g. to improve them and add more information). - /// The stashed diagnostics count towards the total error count. - /// When `.abort_if_errors()` is called, these are also emitted. + /// stolen and emitted/cancelled by other stages (e.g. to improve them and + /// add more information). All stashed diagnostics must be emitted with + /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped, + /// otherwise an assertion failure will occur. stashed_diagnostics: FxIndexMap<(Span, StashKey), Diagnostic>, future_breakage_diagnostics: Vec, @@ -558,7 +559,9 @@ pub struct DiagCtxtFlags { impl Drop for DiagCtxtInner { fn drop(&mut self) { - self.emit_stashed_diagnostics(); + // Any stashed diagnostics should have been handled by + // `emit_stashed_diagnostics` by now. + assert!(self.stashed_diagnostics.is_empty()); if self.err_guars.is_empty() { self.flush_delayed() @@ -750,7 +753,7 @@ impl DiagCtxt { } /// Emit all stashed diagnostics. - pub fn emit_stashed_diagnostics(&self) { + pub fn emit_stashed_diagnostics(&self) -> Option { self.inner.borrow_mut().emit_stashed_diagnostics() } @@ -796,7 +799,9 @@ impl DiagCtxt { pub fn print_error_count(&self, registry: &Registry) { let mut inner = self.inner.borrow_mut(); - inner.emit_stashed_diagnostics(); + // Any stashed diagnostics should have been handled by + // `emit_stashed_diagnostics` by now. + assert!(inner.stashed_diagnostics.is_empty()); if inner.treat_err_as_bug() { return; @@ -872,9 +877,7 @@ impl DiagCtxt { } pub fn abort_if_errors(&self) { - let mut inner = self.inner.borrow_mut(); - inner.emit_stashed_diagnostics(); - if !inner.err_guars.is_empty() { + if self.has_errors().is_some() { FatalError.raise(); } } @@ -1275,7 +1278,8 @@ impl DiagCtxt { // `DiagCtxtInner::foo`. impl DiagCtxtInner { /// Emit all stashed diagnostics. - fn emit_stashed_diagnostics(&mut self) { + fn emit_stashed_diagnostics(&mut self) -> Option { + let mut guar = None; let has_errors = !self.err_guars.is_empty(); for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { if diag.is_error() { @@ -1290,8 +1294,9 @@ impl DiagCtxtInner { continue; } } - self.emit_diagnostic(diag); + guar = guar.or(self.emit_diagnostic(diag)); } + guar } // Return value is only `Some` if the level is `Error` or `DelayedBug`. @@ -1493,6 +1498,11 @@ impl DiagCtxtInner { } fn flush_delayed(&mut self) { + // Stashed diagnostics must be emitted before delayed bugs are flushed. + // Otherwise, we might ICE prematurely when errors would have + // eventually happened. + assert!(self.stashed_diagnostics.is_empty()); + if self.delayed_bugs.is_empty() { return; } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 8a4705e0056e1..cd7957c3bce29 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -423,18 +423,43 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se Compiler { sess, codegen_backend, override_queries: config.override_queries }; rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { - let r = { - let _sess_abort_error = defer(|| { - compiler.sess.finish_diagnostics(&config.registry); + // There are two paths out of `f`. + // - Normal exit. + // - Panic, e.g. triggered by `abort_if_errors`. + // + // We must run `finish_diagnostics` in both cases. + let res = { + // If `f` panics, `finish_diagnostics` will run during + // unwinding because of the `defer`. + let mut guar = None; + let sess_abort_guard = defer(|| { + guar = compiler.sess.finish_diagnostics(&config.registry); }); - f(&compiler) + 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 `finish_diagnostics` emits errors (e.g. stashed + // errors) we can't return an error directly, because the + // return type of this function is `R`, not `Result`. + // 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 guar.is_some() { + compiler.sess.dcx().abort_if_errors(); + } + + res }; let prof = compiler.sess.prof.clone(); - prof.generic_activity("drop_compiler").run(move || drop(compiler)); - r + + res }) }, ) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 858db594b4773..d35c2be1fb47d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -772,12 +772,11 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // lot of annoying errors in the ui tests (basically, // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis - if let Some(reported) = sess.dcx().has_errors_excluding_lint_errors() { - return Err(reported); - } else if sess.dcx().stashed_err_count() > 0 { - // Without this case we sometimes get delayed bug ICEs and I don't - // understand why. -nnethercote - return Err(sess.dcx().delayed_bug("some stashed error is waiting for use")); + // + // 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); } sess.time("misc_checking_3", || { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 211bcb9da94db..8170c0a5a1a9f 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -222,12 +222,12 @@ impl<'tcx> Queries<'tcx> { pub fn codegen_and_build_linker(&'tcx self) -> Result { self.global_ctxt()?.enter(|tcx| { - // Don't do code generation if there were any errors - self.compiler.sess.compile_status()?; - - // If we have any delayed bugs, for example because we created TyKind::Error earlier, - // it's likely that codegen will only cause more ICEs, obscuring the original problem - self.compiler.sess.dcx().flush_delayed(); + // 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) = self.compiler.sess.dcx().has_errors_or_delayed_bugs() { + return Err(guar); + } // Hook for UI tests. Self::check_for_rustc_errors_attr(tcx); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 486396b067726..a3106856a6701 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -237,7 +237,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { ty::Adt(adt, _) => adt.variant_of_res(res), - _ => span_bug!(lhs.span, "non-ADT in tuple struct pattern"), + _ => { + self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern"); + return; + } }; let dotdot = dotdot.as_opt_usize().unwrap_or(pats.len()); let first_n = pats.iter().enumerate().take(dotdot); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f8a1d79659d95..48a18fca27ed2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -258,7 +258,8 @@ impl Session { } } - fn check_miri_unleashed_features(&self) { + fn check_miri_unleashed_features(&self) -> Option { + let mut guar = None; let unleashed_features = self.miri_unleashed_features.lock(); if !unleashed_features.is_empty() { let mut must_err = false; @@ -279,18 +280,22 @@ impl Session { // If we should err, make sure we did. if must_err && self.dcx().has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. - self.dcx().emit_err(errors::NotCircumventFeature); + guar = Some(self.dcx().emit_err(errors::NotCircumventFeature)); } } + guar } /// Invoked all the way at the end to finish off diagnostics printing. - pub fn finish_diagnostics(&self, registry: &Registry) { - self.check_miri_unleashed_features(); + pub fn finish_diagnostics(&self, registry: &Registry) -> Option { + let mut guar = None; + guar = guar.or(self.check_miri_unleashed_features()); + guar = guar.or(self.dcx().emit_stashed_diagnostics()); self.dcx().print_error_count(registry); if self.opts.json_future_incompat { self.dcx().emit_future_breakage_report(); } + guar } /// Returns true if the crate is a testing one. @@ -314,7 +319,6 @@ impl Session { pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { if let Some(reported) = self.dcx().has_errors() { - self.dcx().emit_stashed_diagnostics(); Err(reported) } else { Ok(()) diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr index 0e3cd2ff06099..e4c8aec397365 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -21,5 +21,3 @@ LL | same_output(foo, rpit); query stack during panic: end of query stack -error: aborting due to 2 previous errors - diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr index f9772b2d5a699..523ca229b06f4 100644 --- a/tests/ui/inference/issue-80409.no-compat.stderr +++ b/tests/ui/inference/issue-80409.no-compat.stderr @@ -12,5 +12,3 @@ LL | builder.state().on_entry(|_| {}); query stack during panic: end of query stack -error: aborting due to 1 previous error - diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index fd76526644bdd..069292239bc89 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -21,5 +21,3 @@ LL | query(get_rpit); query stack during panic: end of query stack -error: aborting due to 2 previous errors - From c2512a130f398d923229c3dc401be10c357a3b8d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 19 Feb 2024 10:13:51 +1100 Subject: [PATCH 6/9] Inline and remove `Session::compile_status`. Because it's now simple enough that it doesn't provide much benefit. --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +++- compiler/rustc_driver_impl/src/lib.rs | 17 ++++++++++++----- compiler/rustc_interface/src/queries.rs | 4 +++- compiler/rustc_session/src/session.rs | 8 -------- src/tools/miri/src/bin/miri.rs | 2 +- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 435b517e602b1..7e3f324fe14c2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -487,7 +487,9 @@ fn collate_raw_dylibs<'a, 'b>( } } } - sess.compile_status()?; + if let Some(guar) = sess.dcx().has_errors() { + return Err(guar); + } Ok(dylib_table .into_iter() .map(|(name, imports)| { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 9b2d760282f1c..1057235c0a2a8 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -357,18 +357,25 @@ fn run_compiler( let sess = &compiler.sess; let codegen_backend = &*compiler.codegen_backend; + // This is used for early exits unrelated to errors. E.g. when just + // printing some information without compiling, or exiting immediately + // after parsing, etc. + let early_exit = || { + if let Some(guar) = sess.dcx().has_errors() { Err(guar) } else { Ok(()) } + }; + // This implements `-Whelp`. It should be handled very early, like // `--help`/`-Zhelp`/`-Chelp`. This is the earliest it can run, because // it must happen after lints are registered, during session creation. if sess.opts.describe_lints { describe_lints(sess); - return sess.compile_status(); + return early_exit(); } let early_dcx = EarlyDiagCtxt::new(sess.opts.error_format); if print_crate_info(&early_dcx, codegen_backend, sess, has_input) == Compilation::Stop { - return sess.compile_status(); + return early_exit(); } if !has_input { @@ -377,16 +384,16 @@ fn run_compiler( if !sess.opts.unstable_opts.ls.is_empty() { list_metadata(&early_dcx, sess, &*codegen_backend.metadata_loader()); - return sess.compile_status(); + return early_exit(); } if sess.opts.unstable_opts.link_only { process_rlink(sess, compiler); - return sess.compile_status(); + return early_exit(); } let linker = compiler.enter(|queries| { - let early_exit = || sess.compile_status().map(|_| None); + let early_exit = || early_exit().map(|_| None); queries.parse()?; if let Some(ppm) = &sess.opts.pretty { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 8170c0a5a1a9f..86858bfe41d81 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -261,7 +261,9 @@ impl Linker { let (codegen_results, work_products) = codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames); - sess.compile_status()?; + if let Some(guar) = sess.dcx().has_errors() { + return Err(guar); + } sess.time("serialize_work_products", || { rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 48a18fca27ed2..02c7a0c6371f9 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -317,14 +317,6 @@ impl Session { err } - pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { - if let Some(reported) = self.dcx().has_errors() { - Err(reported) - } else { - Ok(()) - } - } - /// Record the fact that we called `trimmed_def_paths`, and do some /// checking about whether its cost was justified. pub fn record_trimmed_def_paths(&self) { diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index db4c4a28debb4..8a7133fea438d 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -68,7 +68,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { queries: &'tcx rustc_interface::Queries<'tcx>, ) -> Compilation { queries.global_ctxt().unwrap().enter(|tcx| { - if tcx.sess.compile_status().is_err() { + if tcx.sess.dcx().has_errors().is_some() { tcx.dcx().fatal("miri cannot be run on programs that fail compilation"); } From 44006444c8c85a0102984a4323755da0084a681e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 19 Feb 2024 10:27:23 +1100 Subject: [PATCH 7/9] Refactor `run_global_ctxt`. It currently is infallible and uses `abort_if_errors` and `FatalError.raise()` to signal errors. It's easy to instead return a `Result<_, ErrorGuaranteed>`, which is the more usual way of doing things. --- src/librustdoc/core.rs | 15 +++++++++------ src/librustdoc/lib.rs | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 3f7edd049a713..c662f054d0524 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -3,7 +3,7 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordSet; use rustc_errors::emitter::{DynEmitter, HumanEmitter}; use rustc_errors::json::JsonEmitter; -use rustc_errors::{codes::*, TerminalUrl}; +use rustc_errors::{codes::*, ErrorGuaranteed, TerminalUrl}; use rustc_feature::UnstableFeatures; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId}; @@ -306,7 +306,7 @@ pub(crate) fn run_global_ctxt( show_coverage: bool, render_options: RenderOptions, output_format: OutputFormat, -) -> (clean::Crate, RenderOptions, Cache) { +) -> Result<(clean::Crate, RenderOptions, Cache), ErrorGuaranteed> { // Certain queries assume that some checks were run elsewhere // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), // so type-check everything other than function bodies in this crate before running lints. @@ -331,7 +331,10 @@ pub(crate) fn run_global_ctxt( }); }); - tcx.dcx().abort_if_errors(); + if let Some(guar) = tcx.dcx().has_errors() { + return Err(guar); + } + tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx)); tcx.sess.time("check_mod_attrs", || { tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module)) @@ -452,13 +455,13 @@ pub(crate) fn run_global_ctxt( tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc))); - if tcx.dcx().has_errors().is_some() { - rustc_errors::FatalError.raise(); + if let Some(guar) = tcx.dcx().has_errors() { + return Err(guar); } krate = tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate)); - (krate, ctxt.render_options, ctxt.cache) + Ok((krate, ctxt.render_options, ctxt.cache)) } /// Due to , diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 18ea49c5baf1b..f88381ad788d6 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -787,7 +787,7 @@ fn main_args( gcx.enter(|tcx| { let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || { core::run_global_ctxt(tcx, show_coverage, render_options, output_format) - }); + })?; info!("finished with rustc"); if let Some(options) = scrape_examples_options { From 4da67fff61ccc460370df6047563f8091c7e66bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 19 Feb 2024 10:23:58 +1100 Subject: [PATCH 8/9] Replace unnecessary `abort_if_errors`. Replace `abort_if_errors` calls that are certain to abort -- because we emit an error immediately beforehand -- with `FatalErro.raise()`. --- compiler/rustc_codegen_ssa/src/back/link.rs | 9 +++------ compiler/rustc_codegen_ssa/src/base.rs | 5 +---- compiler/rustc_errors/src/lib.rs | 4 ++++ compiler/rustc_interface/src/passes.rs | 4 +--- compiler/rustc_session/src/output.rs | 3 ++- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 11 ++--------- 6 files changed, 13 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7e3f324fe14c2..1ad0dec064006 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3,7 +3,7 @@ use rustc_ast::CRATE_NODE_ID; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{DiagCtxt, ErrorGuaranteed}; +use rustc_errors::{DiagCtxt, ErrorGuaranteed, FatalError}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; @@ -722,10 +722,7 @@ fn link_dwarf_object<'a>( Ok(()) }) { Ok(()) => {} - Err(e) => { - sess.dcx().emit_err(errors::ThorinErrorWrapper(e)); - sess.dcx().abort_if_errors(); - } + Err(e) => sess.dcx().emit_fatal(errors::ThorinErrorWrapper(e)), } } @@ -1001,7 +998,7 @@ fn link_natively<'a>( sess.dcx().emit_note(errors::CheckInstalledVisualStudio); sess.dcx().emit_note(errors::InsufficientVSCodeProduct); } - sess.dcx().abort_if_errors(); + FatalError.raise(); } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 760b3f30ee51e..f7afd22a48cab 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -449,10 +449,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let Some(llfn) = cx.declare_c_main(llfty) else { // FIXME: We should be smart and show a better diagnostic here. let span = cx.tcx().def_span(rust_main_def_id); - let dcx = cx.tcx().dcx(); - dcx.emit_err(errors::MultipleMainFunctions { span }); - dcx.abort_if_errors(); - bug!(); + cx.tcx().dcx().emit_fatal(errors::MultipleMainFunctions { span }); }; // `main` should respect same config for frame pointer elimination as rest of code diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fafd636bb7091..7e3d15ffc921f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -876,6 +876,10 @@ impl DiagCtxt { } } + /// This excludes delayed bugs and stashed errors. Used for early aborts + /// after errors occurred -- e.g. because continuing in the face of errors is + /// likely to lead to bad results, such as spurious/uninteresting + /// additional errors -- when returning an error `Result` is difficult. pub fn abort_if_errors(&self) { if self.has_errors().is_some() { FatalError.raise(); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d35c2be1fb47d..661401687593d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -936,9 +936,7 @@ pub fn start_codegen<'tcx>( if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { - let dcx = tcx.dcx(); - dcx.emit_err(errors::CantEmitMIR { error }); - dcx.abort_if_errors(); + tcx.dcx().emit_fatal(errors::CantEmitMIR { error }); } } diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index db976b3040487..74d26237f2463 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -6,6 +6,7 @@ use crate::errors::{ }; use crate::Session; use rustc_ast::{self as ast, attr}; +use rustc_errors::FatalError; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use std::path::Path; @@ -115,7 +116,7 @@ pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option) { } if err_count > 0 { - sess.dcx().abort_if_errors(); + FatalError.raise(); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index aa8bd5fdc866b..7186b96b40d04 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -22,7 +22,7 @@ use crate::traits::{ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, - MultiSpan, StashKey, StringPart, + FatalError, MultiSpan, StashKey, StringPart, }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; @@ -193,14 +193,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit); mutate(&mut err); err.emit(); - - self.dcx().abort_if_errors(); - // FIXME: this should be something like `build_overflow_error_fatal`, which returns - // `DiagnosticBuilder<', !>`. Then we don't even need anything after that `emit()`. - unreachable!( - "did not expect compilation to continue after `abort_if_errors`, \ - since an error was definitely emitted!" - ); + FatalError.raise(); } fn build_overflow_error( From f16c226af3ad4d21021433745214c71e95f10236 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 19 Feb 2024 13:51:53 +1100 Subject: [PATCH 9/9] Inline and remove `abort_on_err`. It's clumsy and doesn't improve readability. --- compiler/rustc_driver_impl/src/lib.rs | 17 ++++------------- compiler/rustc_driver_impl/src/pretty.rs | 14 ++++++++++---- src/librustdoc/lib.rs | 5 ++--- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1057235c0a2a8..692c059beb0c4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -144,16 +144,6 @@ pub const EXIT_FAILURE: i32 = 1; pub const DEFAULT_BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md"; -pub fn abort_on_err(result: Result, sess: &Session) -> T { - match result { - Err(..) => { - sess.dcx().abort_if_errors(); - panic!("error reported but abort_if_errors didn't abort???"); - } - Ok(x) => x, - } -} - pub trait Callbacks { /// Called before creating the compiler instance fn config(&mut self, _config: &mut interface::Config) {} @@ -665,10 +655,11 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) { }; } }; - let result = compiler.codegen_backend.link(sess, codegen_results, &outputs); - abort_on_err(result, sess); + if compiler.codegen_backend.link(sess, codegen_results, &outputs).is_err() { + FatalError.raise(); + } } else { - dcx.emit_fatal(RlinkNotAFile {}) + dcx.emit_fatal(RlinkNotAFile {}); } } diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index e5a7d5501151a..ff5ffd2454a1f 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -2,6 +2,7 @@ use rustc_ast as ast; use rustc_ast_pretty::pprust as pprust_ast; +use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir_pretty as pprust_hir; use rustc_middle::bug; @@ -18,7 +19,6 @@ use std::fmt::Write; pub use self::PpMode::*; pub use self::PpSourceMode::*; -use crate::abort_on_err; struct AstNoAnn; @@ -243,7 +243,9 @@ impl<'tcx> PrintExtra<'tcx> { pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { if ppm.needs_analysis() { - abort_on_err(ex.tcx().analysis(()), sess); + if ex.tcx().analysis(()).is_err() { + FatalError.raise(); + } } let (src, src_name) = get_source(sess); @@ -334,7 +336,9 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ThirTree => { let tcx = ex.tcx(); let mut out = String::new(); - abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess); + if rustc_hir_analysis::check_crate(tcx).is_err() { + FatalError.raise(); + } debug!("pretty printing THIR tree"); for did in tcx.hir().body_owners() { let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did)); @@ -344,7 +348,9 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ThirFlat => { let tcx = ex.tcx(); let mut out = String::new(); - abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess); + if rustc_hir_analysis::check_crate(tcx).is_err() { + FatalError.raise(); + } debug!("pretty printing THIR flat"); for did in tcx.hir().body_owners() { let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did)); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f88381ad788d6..33837fe5652ce 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -78,8 +78,7 @@ use std::io::{self, IsTerminal}; use std::process; use std::sync::{atomic::AtomicBool, Arc}; -use rustc_driver::abort_on_err; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{ErrorGuaranteed, FatalError}; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; @@ -779,7 +778,7 @@ fn main_args( } compiler.enter(|queries| { - let mut gcx = abort_on_err(queries.global_ctxt(), sess); + let Ok(mut gcx) = queries.global_ctxt() else { FatalError.raise() }; if sess.dcx().has_errors().is_some() { sess.dcx().fatal("Compilation failed, aborting rustdoc"); }