]> git.lizzy.rs Git - rust.git/commitdiff
rustc_error: make ErrorReported impossible to construct
authormark <markm@cs.wisc.edu>
Sun, 23 Jan 2022 00:49:12 +0000 (18:49 -0600)
committermark <markm@cs.wisc.edu>
Wed, 16 Mar 2022 15:35:24 +0000 (10:35 -0500)
There are a few places were we have to construct it, though, and a few
places that are more invasive to change. To do this, we create a
constructor with a long obvious name.

104 files changed:
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_ssa/src/mir/mod.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/interpret/intern.rs
compiler/rustc_const_eval/src/interpret/operand.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_errors/src/diagnostic_builder.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/proc_macro.rs
compiler/rustc_incremental/src/persist/fs.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
compiler/rustc_infer/src/infer/outlives/obligations.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/queries.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/early.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/non_ascii_idents.rs
compiler/rustc_lint/src/noop_method_call.rs
compiler/rustc_lint/src/traits.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/stability.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/specialization_graph.rs
compiler/rustc_middle/src/ty/adt.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/cx/mod.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_transform/src/check_const_item_mutation.rs
compiler/rustc_mir_transform/src/check_packed_ref.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/liveness.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_session/src/output.rs
compiler/rustc_session/src/session.rs
compiler/rustc_trait_selection/src/traits/codegen.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/specialize/mod.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_typeck/src/astconv/errors.rs
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/cast.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/dropck.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/coherence/orphan.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
compiler/rustc_typeck/src/lib.rs
src/librustdoc/clean/types.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/lib.rs
src/librustdoc/passes/bare_urls.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/passes/check_doc_test_visibility.rs
src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
src/tools/rustfmt/src/parse/macros/lazy_static.rs
src/tools/rustfmt/src/parse/macros/mod.rs
src/tools/rustfmt/src/parse/session.rs

index c1680be9c0ad5af0acecf4c90a45d897cb68de3b..abf1bc739a3f78243df4b75c9bbf6aaa16bda4bc 100644 (file)
@@ -952,7 +952,7 @@ fn unwrap_single_token(sess: &Session, tokens: TokenStream, span: Span) -> Token
                                 sess.diagnostic().delay_span_bug(
                                     span,
                                     "unexpected delimiter in key-value attribute's value",
-                                )
+                                );
                             }
                             unwrap_single_token(sess, tokens, span)
                         }
index 8f0b12cb4feef17d86420aa2181b40a9b63c2746..f5e6b15fcbfd115784f682984af8a2f4ab291144 100644 (file)
@@ -440,7 +440,7 @@ fn check_decl_attrs(&self, fn_decl: &FnDecl) {
                         attr.span,
                         "allow, cfg, cfg_attr, deny, \
                 forbid, and warn are the only allowed built-in attributes in function parameters",
-                    )
+                    );
                 }
             });
     }
index 097bd07c74ce8a5ba6dca07e3f11d9bb113c423e..5b6147c72230d53b943586280b3a6d457d103886 100644 (file)
@@ -252,11 +252,12 @@ fn check_abi(&self, abi: ast::StrLit) {
                     "wasm ABI is experimental and subject to change"
                 );
             }
-            abi => self
-                .sess
-                .parse_sess
-                .span_diagnostic
-                .delay_span_bug(span, &format!("unrecognized ABI not caught in lowering: {}", abi)),
+            abi => {
+                self.sess.parse_sess.span_diagnostic.delay_span_bug(
+                    span,
+                    &format!("unrecognized ABI not caught in lowering: {}", abi),
+                );
+            }
         }
     }
 
index 7502a3e39a1910f9a7e20ca0241109be2e0ee35a..c9c973bd34350267fb0520a326cef38eec911b74 100644 (file)
@@ -178,7 +178,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     // Gather the upvars of a closure, if any.
     let tables = tcx.typeck_opt_const_arg(def);
-    if let Some(ErrorGuaranteed) = tables.tainted_by_errors {
+    if let Some(ErrorGuaranteed { .. }) = tables.tainted_by_errors {
         infcx.set_tainted_by_errors();
         errors.set_tainted_by_errors();
     }
@@ -2274,6 +2274,8 @@ fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field>
 }
 
 mod error {
+    use rustc_errors::ErrorGuaranteed;
+
     use super::*;
 
     pub struct BorrowckErrors<'tcx> {
@@ -2311,7 +2313,7 @@ pub fn new() -> Self {
         // FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is
         // set before any emission actually happens (weakening the guarantee).
         pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
-            self.tainted_by_errors = Some(ErrorGuaranteed {});
+            self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
             t.buffer(&mut self.buffered);
         }
 
@@ -2320,7 +2322,7 @@ pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
         }
 
         pub fn set_tainted_by_errors(&mut self) {
-            self.tainted_by_errors = Some(ErrorGuaranteed {});
+            self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
         }
     }
 
index aff3603303a98ff8f90120303d3804bbac681487..4657791345b8eb22d3f0d1c304d829ca2132c2ff 100644 (file)
@@ -1,7 +1,6 @@
 //! Handling of `static`s, `const`s and promoted allocations
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::ErrorGuaranteed;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{
     read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
@@ -54,7 +53,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
                 {
                     all_constants_ok = false;
                     match err {
-                        ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {
+                        ErrorHandled::Reported(_) | ErrorHandled::Linted => {
                             fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
                         }
                         ErrorHandled::TooGeneric => {
index 40a8e2388e26ba50f8c8654b1df844cc3e2eb7c5..6c139df0a8555c35109549a12a7305bad2bccc6a 100644 (file)
@@ -1,5 +1,4 @@
 use crate::traits::*;
-use rustc_errors::ErrorGuaranteed;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
@@ -191,7 +190,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             all_consts_ok = false;
             match err {
                 // errored or at least linted
-                ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {}
+                ErrorHandled::Reported(_) | ErrorHandled::Linted => {}
                 ErrorHandled::TooGeneric => {
                     span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err)
                 }
index 92f4d3a6772444d79638249261ddcbc8fd7aa48c..2b58c1e8233c1bb6bf35384c5a459347af4f38ca 100644 (file)
@@ -1,4 +1,3 @@
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty};
@@ -247,11 +246,11 @@ fn load_mir(
                 if ecx.tcx.is_ctfe_mir_available(def.did) {
                     Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
                 } else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst {
-                    ecx.tcx.sess.delay_span_bug(
+                    let guar = ecx.tcx.sess.delay_span_bug(
                         rustc_span::DUMMY_SP,
                         "This is likely a const item that is missing from its impl",
                     );
-                    throw_inval!(AlreadyReported(ErrorGuaranteed {}));
+                    throw_inval!(AlreadyReported(guar));
                 } else {
                     let path = ecx.tcx.def_path_str(def.did);
                     Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path))
index 9f507bface221766697db7bdf426e4a18099ecfa..43ab74f4b888a21794f055bb3442d20eab46dff7 100644 (file)
@@ -406,8 +406,11 @@ pub fn intern_const_alloc_recursive<
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // Codegen does not like dangling pointers, and generally `tcx` assumes that
             // all allocations referenced anywhere actually exist. So, make sure we error here.
-            ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
-            return Err(ErrorGuaranteed);
+            let reported = ecx
+                .tcx
+                .sess
+                .span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
+            return Err(reported);
         } else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
             // We have hit an `AllocId` that is neither in local or global memory and isn't
             // marked as dangling by local memory.  That should be impossible.
index 2fae53bb9bdf5bc8c8db5966197c2f54e48974e6..9000567558b84cf6974678545af388fb0508c3b8 100644 (file)
@@ -4,12 +4,11 @@
 use std::convert::TryFrom;
 use std::fmt::Write;
 
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
 use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
-use rustc_middle::ty::{ConstInt, Ty};
+use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty};
 use rustc_middle::{mir, ty};
 use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
@@ -565,7 +564,9 @@ pub fn const_to_op(
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         match val.val() {
             ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
-            ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorGuaranteed)),
+            ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
+                throw_inval!(AlreadyReported(reported))
+            }
             ty::ConstKind::Unevaluated(uv) => {
                 let instance = self.resolve(uv.def, uv.substs)?;
                 Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
index 7dc279cc840fba930b174c3e11b720e82c91d9d8..eb01e261c1a55706a94c3cbd6814809e3e215c42 100644 (file)
@@ -259,7 +259,7 @@ pub fn check_body(&mut self) {
                 self.tcx.sess.diagnostic().emit_diagnostic(&error);
             }
         } else {
-            assert!(self.tcx.sess.has_errors());
+            assert!(self.tcx.sess.has_errors().is_some());
         }
     }
 
@@ -327,8 +327,8 @@ pub fn check_op_spanned<O: NonConstOp<'tcx>>(&mut self, op: O, span: Span) {
 
         match op.importance() {
             ops::DiagnosticImportance::Primary => {
-                self.error_emitted = Some(ErrorGuaranteed);
-                err.emit();
+                let reported = err.emit();
+                self.error_emitted = Some(reported);
             }
 
             ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),
index 43c9e9296b90aab2928f7ba275e1d5ef2d6eff12..91bb38e5a95d5321e758e9810b977fd2abe3dab7 100644 (file)
@@ -235,7 +235,7 @@ fn run_compiler(
     };
 
     match make_input(config.opts.error_format, &matches.free) {
-        Err(ErrorGuaranteed) => return Err(ErrorGuaranteed),
+        Err(reported) => return Err(reported),
         Ok(Some((input, input_file_path))) => {
             config.input = input;
             config.input_path = input_file_path;
@@ -465,11 +465,11 @@ fn make_input(
             if io::stdin().read_to_string(&mut src).is_err() {
                 // Immediately stop compilation if there was an issue reading
                 // the input (for example if the input stream is not UTF-8).
-                early_error_no_abort(
+                let reported = early_error_no_abort(
                     error_format,
                     "couldn't read from stdin, as it did not contain valid UTF-8",
                 );
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
             if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
                 let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
@@ -1128,7 +1128,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
 pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
     catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
         if value.is::<rustc_errors::FatalErrorMarker>() {
-            ErrorGuaranteed
+            ErrorGuaranteed::unchecked_claim_error_was_emitted()
         } else {
             panic::resume_unwind(value);
         }
index 98b8b2a569edde1bfb6f4f5e1261cb3e2e99087b..72471638a966bbb4fffd7ef0ec5628de47691808 100644 (file)
@@ -128,7 +128,7 @@ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Se
             DiagnosticBuilderState::Emittable(handler) => {
                 db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
 
-                handler.emit_diagnostic(&db.inner.diagnostic);
+                let guar = handler.emit_diagnostic(&db.inner.diagnostic);
 
                 // Only allow a guarantee if the `level` wasn't switched to a
                 // non-error - the field isn't `pub`, but the whole `Diagnostic`
@@ -139,7 +139,7 @@ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Se
                      from `DiagnosticBuilder<ErrorGuaranteed>`",
                     db.inner.diagnostic.level,
                 );
-                ErrorGuaranteed
+                guar.unwrap()
             }
             // `.emit()` was previously called, disallowed from repeating it,
             // but can take advantage of the previous `.emit()`'s guarantee
@@ -154,7 +154,7 @@ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Se
                      became non-error ({:?}), after original `.emit()`",
                     db.inner.diagnostic.level,
                 );
-                ErrorGuaranteed
+                ErrorGuaranteed::unchecked_claim_error_was_emitted()
             }
         }
     }
index 345247b07001b6cfe1d44a3c8da31a5a2c516209..c719e4910ce4eaa3942536193e9abacb0f855adb 100644 (file)
@@ -399,7 +399,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl error::Error for ExplicitBug {}
 
 pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
-pub use diagnostic_builder::DiagnosticBuilder;
+pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
 use std::backtrace::Backtrace;
 
 /// A handler deals with errors and other compiler output.
@@ -644,8 +644,8 @@ pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBu
     }
 
     /// Emit all stashed diagnostics.
-    pub fn emit_stashed_diagnostics(&self) {
-        self.inner.borrow_mut().emit_stashed_diagnostics();
+    pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
+        self.inner.borrow_mut().emit_stashed_diagnostics()
     }
 
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
@@ -805,8 +805,8 @@ pub fn span_fatal_with_code(
         FatalError.raise()
     }
 
-    pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
-        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
+    pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
+        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
     }
 
     pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
@@ -829,7 +829,7 @@ pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ! {
     }
 
     #[track_caller]
-    pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) {
+    pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
         self.inner.borrow_mut().delay_span_bug(span, msg)
     }
 
@@ -858,8 +858,8 @@ pub fn fatal(&self, msg: &str) -> FatalError {
         self.inner.borrow_mut().fatal(msg)
     }
 
-    pub fn err(&self, msg: &str) {
-        self.inner.borrow_mut().err(msg);
+    pub fn err(&self, msg: &str) -> ErrorGuaranteed {
+        self.inner.borrow_mut().err(msg)
     }
 
     pub fn warn(&self, msg: &str) {
@@ -880,11 +880,15 @@ pub fn err_count(&self) -> usize {
         self.inner.borrow().err_count()
     }
 
-    pub fn has_errors(&self) -> bool {
-        self.inner.borrow().has_errors()
+    pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
+        if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
     }
-    pub fn has_errors_or_lint_errors(&self) -> bool {
-        self.inner.borrow().has_errors_or_lint_errors()
+    pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
+        if self.inner.borrow().has_errors_or_lint_errors() {
+            Some(ErrorGuaranteed(()))
+        } else {
+            None
+        }
     }
     pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.inner.borrow().has_errors_or_delayed_span_bugs()
@@ -915,13 +919,17 @@ pub fn force_print_diagnostic(&self, db: Diagnostic) {
         self.inner.borrow_mut().force_print_diagnostic(db)
     }
 
-    pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) {
+    pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
         self.inner.borrow_mut().emit_diagnostic(diagnostic)
     }
 
-    fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
+    fn emit_diag_at_span(
+        &self,
+        mut diag: Diagnostic,
+        sp: impl Into<MultiSpan>,
+    ) -> Option<ErrorGuaranteed> {
         let mut inner = self.inner.borrow_mut();
-        inner.emit_diagnostic(diag.set_span(sp));
+        inner.emit_diagnostic(diag.set_span(sp))
     }
 
     pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
@@ -990,13 +998,20 @@ fn force_print_diagnostic(&mut self, db: Diagnostic) {
     }
 
     /// Emit all stashed diagnostics.
-    fn emit_stashed_diagnostics(&mut self) {
+    fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
-        diags.iter().for_each(|diag| self.emit_diagnostic(diag));
+        let mut reported = None;
+        diags.iter().for_each(|diag| {
+            if diag.is_error() {
+                reported = Some(ErrorGuaranteed(()));
+            }
+            self.emit_diagnostic(diag);
+        });
+        reported
     }
 
     // FIXME(eddyb) this should ideally take `diagnostic` by value.
-    fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
+    fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
         if diagnostic.level == Level::DelayedBug {
             // FIXME(eddyb) this should check for `has_errors` and stop pushing
             // once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1005,7 +1020,7 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             self.delayed_span_bugs.push(diagnostic.clone());
 
             if !self.flags.report_delayed_bugs {
-                return;
+                return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
             }
         }
 
@@ -1020,7 +1035,7 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             if diagnostic.has_future_breakage() {
                 (*TRACK_DIAGNOSTICS)(diagnostic);
             }
-            return;
+            return None;
         }
 
         // The `LintExpectationId` can be stable or unstable depending on when it was created.
@@ -1029,16 +1044,16 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
         // a stable one by the `LintLevelsBuilder`.
         if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
             self.unstable_expect_diagnostics.push(diagnostic.clone());
-            return;
+            return None;
         }
 
         (*TRACK_DIAGNOSTICS)(diagnostic);
 
         if let Level::Expect(expectation_id) = diagnostic.level {
             self.fulfilled_expectations.insert(expectation_id);
-            return;
+            return None;
         } else if diagnostic.level == Allow {
-            return;
+            return None;
         }
 
         if let Some(ref code) = diagnostic.code {
@@ -1068,8 +1083,12 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             } else {
                 self.bump_err_count();
             }
+
+            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
         } else {
             self.bump_warn_count();
+
+            None
         }
     }
 
@@ -1191,7 +1210,7 @@ fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>)
     }
 
     #[track_caller]
-    fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
+    fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
         // FIXME: Would be nice to increment err_count in a more coherent way.
@@ -1202,7 +1221,7 @@ fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
         let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
         diagnostic.set_span(sp.into());
         diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
-        self.emit_diagnostic(&diagnostic)
+        self.emit_diagnostic(&diagnostic).unwrap()
     }
 
     // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
@@ -1221,20 +1240,20 @@ fn failure(&mut self, msg: &str) {
     }
 
     fn fatal(&mut self, msg: &str) -> FatalError {
-        self.emit_error(Fatal, msg);
+        self.emit(Fatal, msg);
         FatalError
     }
 
-    fn err(&mut self, msg: &str) {
-        self.emit_error(Error { lint: false }, msg);
+    fn err(&mut self, msg: &str) -> ErrorGuaranteed {
+        self.emit(Error { lint: false }, msg)
     }
 
     /// Emit an error; level should be `Error` or `Fatal`.
-    fn emit_error(&mut self, level: Level, msg: &str) {
+    fn emit(&mut self, level: Level, msg: &str) -> ErrorGuaranteed {
         if self.treat_err_as_bug() {
             self.bug(msg);
         }
-        self.emit_diagnostic(&Diagnostic::new(level, msg));
+        self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap()
     }
 
     fn bug(&mut self, msg: &str) -> ! {
@@ -1433,9 +1452,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
     );
 }
 
-// Useful type to use with `Result<>` indicate that an error has already
-// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)]
-pub struct ErrorGuaranteed;
+/// Useful type to use with `Result<>` indicate that an error has already
+/// been reported to the user, so no need to continue checking.
+#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ErrorGuaranteed(());
+
+impl ErrorGuaranteed {
+    /// To be used only if you really know what you are doing... ideally, we would find a way to
+    /// eliminate all calls to this method.
+    pub fn unchecked_claim_error_was_emitted() -> Self {
+        ErrorGuaranteed(())
+    }
+}
 
 rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);
index 1263f31f6aa1b9635373a5cd02a431550cec8d43..d6b308cdf85d59359d2ee8eae8edeaa5ed70ce1e 100644 (file)
@@ -1330,7 +1330,7 @@ pub fn parse_macro_name_and_helper_attrs(
     let attributes_attr = list.get(1);
     let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
         if !attr.has_name(sym::attributes) {
-            diag.span_err(attr.span(), "second argument must be `attributes`")
+            diag.span_err(attr.span(), "second argument must be `attributes`");
         }
         attr.meta_item_list()
             .unwrap_or_else(|| {
index c3b1b34aa29b933ba6863d71afeaec3e15623a57..b93edf8da7a6458f530f4b9492a481a9497cdc28 100644 (file)
@@ -534,10 +534,10 @@ pub fn compile_declarative_macro(
     let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
     match transparency_error {
         Some(TransparencyError::UnknownTransparency(value, span)) => {
-            diag.span_err(span, &format!("unknown macro transparency: `{}`", value))
+            diag.span_err(span, &format!("unknown macro transparency: `{}`", value));
         }
         Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => {
-            diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes")
+            diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes");
         }
         None => {}
     }
@@ -617,7 +617,9 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
 fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
     match *rhs {
         mbe::TokenTree::Delimited(..) => return true,
-        _ => sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"),
+        _ => {
+            sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited");
+        }
     }
     false
 }
index aefbec0e518faa1b3a8e7b1253d79189647d3dab..a5afb7aa4fa4e9bb80232baf04a2e140177c7c62 100644 (file)
@@ -31,8 +31,7 @@ fn expand<'cx>(
             if let Some(s) = e.as_str() {
                 err.help(&format!("message: {}", s));
             }
-            err.emit();
-            ErrorGuaranteed
+            err.emit()
         })
     }
 }
@@ -58,8 +57,7 @@ fn expand<'cx>(
                 if let Some(s) = e.as_str() {
                     err.help(&format!("message: {}", s));
                 }
-                err.emit();
-                ErrorGuaranteed
+                err.emit()
             })
     }
 }
index ed7ec51d6298b81a56fd926a2c4448d87dbfb07d..b13f0b0d3dad81d8c765ca53fd8f3cf3f5752c6e 100644 (file)
@@ -225,12 +225,12 @@ pub fn prepare_session_directory(
     let crate_dir = match crate_dir.canonicalize() {
         Ok(v) => v,
         Err(err) => {
-            sess.err(&format!(
+            let reported = sess.err(&format!(
                 "incremental compilation: error canonicalizing path `{}`: {}",
                 crate_dir.display(),
                 err
             ));
-            return Err(ErrorGuaranteed);
+            return Err(reported);
         }
     };
 
@@ -489,14 +489,14 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua
             Ok(())
         }
         Err(err) => {
-            sess.err(&format!(
+            let reported = sess.err(&format!(
                 "Could not create incremental compilation {} \
                                directory `{}`: {}",
                 dir_tag,
                 path.display(),
                 err
             ));
-            Err(ErrorGuaranteed)
+            Err(reported)
         }
     }
 }
@@ -545,8 +545,7 @@ fn lock_directory(
                     );
                 }
             }
-            err.emit();
-            Err(ErrorGuaranteed)
+            Err(err.emit())
         }
     }
 }
index 0d6dbd8f34398ccf41a55753df90842b86fc7af5..7721e00c141d788f61f9e59e3a36fba5f33856ae 100644 (file)
@@ -147,8 +147,8 @@ pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorGuaranteed> {
 
         self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
 
-        err.emit();
-        Some(ErrorGuaranteed)
+        let reported = err.emit();
+        Some(reported)
     }
 
     fn suggest_adding_lifetime_params(
index 4710eae6189a5fc087819f915fef1f9b26636d1a..467054e318be53d18a9184caeb4cc75c5f4bbc7b 100644 (file)
@@ -98,7 +98,7 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
             let impl_span = self.tcx().def_span(*impl_def_id);
             err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
         }
-        err.emit();
-        Some(ErrorGuaranteed)
+        let reported = err.emit();
+        Some(reported)
     }
 }
index c7bfa686c04dca66b99aa3d5a4a176ca6d29524f..df81aea6ef9ecfb1ceda0f93dd452fc701883633 100644 (file)
@@ -54,10 +54,7 @@ pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuarant
 
     pub fn try_report(&self) -> Option<ErrorGuaranteed> {
         self.try_report_from_nll()
-            .map(|mut diag| {
-                diag.emit();
-                ErrorGuaranteed
-            })
+            .map(|mut diag| diag.emit())
             .or_else(|| self.try_report_impl_not_conforming_to_trait())
             .or_else(|| self.try_report_anon_anon_conflict())
             .or_else(|| self.try_report_static_impl_trait())
index 99dd418015b14e8fa3c43fbb625624aca29453d2..4fcdcb6366683e3b2b45ac6e383a6fee5e478960 100644 (file)
@@ -84,8 +84,8 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorGuaranteed> {
                         ),
                     );
                     if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
-                        err.emit();
-                        return Some(ErrorGuaranteed);
+                        let reported = err.emit();
+                        return Some(reported);
                     } else {
                         err.cancel();
                     }
@@ -276,8 +276,8 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorGuaranteed> {
             Some((param.param_ty_span, param.param_ty.to_string())),
         );
 
-        err.emit();
-        Some(ErrorGuaranteed)
+        let reported = err.emit();
+        Some(reported)
     }
 }
 
index 3f0f50bb75af150f32cf25ae190e80142565047e..b1a42ee66c9201cbc56397b22c80c20e44fbd1c7 100644 (file)
@@ -33,13 +33,13 @@ pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuar
             ) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
             && sup_expected_found == sub_expected_found
         {
-            self.emit_err(
+            let guar = self.emit_err(
                 var_origin.span(),
                 sub_expected,
                 sub_found,
                 *trait_item_def_id,
             );
-            return Some(ErrorGuaranteed);
+            return Some(guar);
         }
         if let RegionResolutionError::ConcreteFailure(origin, _, _)
             | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
@@ -49,18 +49,24 @@ pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuar
                 trait_item_def_id,
             } = origin
         {
-            self.emit_associated_type_err(
+            let guar = self.emit_associated_type_err(
                 span,
                 self.infcx.tcx.item_name(impl_item_def_id),
                 impl_item_def_id,
                 trait_item_def_id,
             );
-            return Some(ErrorGuaranteed);
+            return Some(guar);
         }
         None
     }
 
-    fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) {
+    fn emit_err(
+        &self,
+        sp: Span,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+        trait_def_id: DefId,
+    ) -> ErrorGuaranteed {
         let trait_sp = self.tcx().def_span(trait_def_id);
         let mut err = self
             .tcx()
@@ -142,7 +148,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
                  argument, the other inputs and its output",
             );
         }
-        err.emit();
+        err.emit()
     }
 
     fn emit_associated_type_err(
@@ -151,7 +157,7 @@ fn emit_associated_type_err(
         item_name: Symbol,
         impl_item_def_id: DefId,
         trait_item_def_id: DefId,
-    ) {
+    ) -> ErrorGuaranteed {
         let impl_sp = self.tcx().def_span(impl_item_def_id);
         let trait_sp = self.tcx().def_span(trait_item_def_id);
         let mut err = self
@@ -161,7 +167,7 @@ fn emit_associated_type_err(
         err.span_label(impl_sp, "found");
         err.span_label(trait_sp, "expected");
 
-        err.emit();
+        err.emit()
     }
 }
 
index 0224aba01ef2884dc22c39c3628e660d56c82ae6..5d8cc94e05c29b36a520598dd90a0a60671f1559 100644 (file)
@@ -189,7 +189,7 @@ pub fn process_registered_region_obligations(
                 self.tcx.sess.delay_span_bug(
                     origin.span(),
                     &format!("no region-bound-pairs for {:?}", body_id),
-                )
+                );
             }
         }
     }
index 1aceb4e95e6138090b2863529ae35fa2bec3383e..4f30e78f5e2aa7efba92581e86ab7bee9b64982e 100644 (file)
@@ -373,7 +373,7 @@ pub fn configure_and_expand(
         if recursion_limit_hit {
             // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
             // with a large AST
-            Err(ErrorGuaranteed)
+            Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
         } else {
             Ok(krate)
         }
@@ -413,7 +413,7 @@ pub fn configure_and_expand(
         );
 
         msg.warn("The generated documentation may be incorrect");
-        msg.emit()
+        msg.emit();
     } else {
         krate = sess.time("maybe_create_a_macro_crate", || {
             let is_test_crate = sess.opts.test;
@@ -742,29 +742,30 @@ pub fn prepare_outputs(
     if let Some(ref input_path) = compiler.input_path {
         if sess.opts.will_create_output_file() {
             if output_contains_path(&output_paths, input_path) {
-                sess.err(&format!(
+                let reported = sess.err(&format!(
                     "the input file \"{}\" would be overwritten by the generated \
                         executable",
                     input_path.display()
                 ));
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
             if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
-                sess.err(&format!(
+                let reported = sess.err(&format!(
                     "the generated executable for the input file \"{}\" conflicts with the \
                         existing directory \"{}\"",
                     input_path.display(),
                     dir_path.display()
                 ));
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
         }
     }
 
     if let Some(ref dir) = compiler.temps_dir {
         if fs::create_dir_all(dir).is_err() {
-            sess.err("failed to find or create the directory specified by `--temps-dir`");
-            return Err(ErrorGuaranteed);
+            let reported =
+                sess.err("failed to find or create the directory specified by `--temps-dir`");
+            return Err(reported);
         }
     }
 
@@ -776,8 +777,9 @@ pub fn prepare_outputs(
     if !only_dep_info {
         if let Some(ref dir) = compiler.output_dir {
             if fs::create_dir_all(dir).is_err() {
-                sess.err("failed to find or create the directory specified by `--out-dir`");
-                return Err(ErrorGuaranteed);
+                let reported =
+                    sess.err("failed to find or create the directory specified by `--out-dir`");
+                return Err(reported);
             }
         }
     }
@@ -987,8 +989,8 @@ 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 sess.has_errors() {
-        return Err(ErrorGuaranteed);
+    if let Some(reported) = sess.has_errors() {
+        return Err(reported);
     }
 
     sess.time("misc_checking_3", || {
index d0e533b457159232c5a193bb57ac661732a2981f..6373f4e9af190eafee9a7f877eae375c2e7770c3 100644 (file)
@@ -5,7 +5,6 @@
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_incremental::DepGraphFuture;
 use rustc_lint::LintStore;
@@ -121,10 +120,8 @@ fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
 
     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();
-                ErrorGuaranteed
-            })
+            passes::parse(self.session(), &self.compiler.input)
+                .map_err(|mut parse_error| parse_error.emit())
         })
     }
 
index 47de4c9be26feb1b726969f6ec6948a7587f90db..50a3df21a3bc9010ea1f04d00fc88facf8f940ca 100644 (file)
@@ -157,7 +157,7 @@ fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
             if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
                 if leaf_ty.is_box() {
                     cx.struct_span_lint(BOX_POINTERS, span, |lint| {
-                        lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit()
+                        lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit();
                     });
                 }
             }
@@ -318,7 +318,7 @@ fn report_unsafe(
         &self,
         cx: &EarlyContext<'_>,
         span: Span,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         // This comes from a macro that has `#[allow_internal_unsafe]`.
         if span.allows_unsafe() {
@@ -350,7 +350,7 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
                                                macros using unsafe without triggering \
                                                the `unsafe_code` lint at their call site",
                 )
-                .emit()
+                .emit();
             });
         }
     }
@@ -360,7 +360,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
             // Don't warn about generated blocks; that'll just pollute the output.
             if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
                 self.report_unsafe(cx, blk.span, |lint| {
-                    lint.build("usage of an `unsafe` block").emit()
+                    lint.build("usage of an `unsafe` block").emit();
                 });
             }
         }
@@ -370,12 +370,12 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         match it.kind {
             ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
                 .report_unsafe(cx, it.span, |lint| {
-                    lint.build("declaration of an `unsafe` trait").emit()
+                    lint.build("declaration of an `unsafe` trait").emit();
                 }),
 
             ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
                 .report_unsafe(cx, it.span, |lint| {
-                    lint.build("implementation of an `unsafe` trait").emit()
+                    lint.build("implementation of an `unsafe` trait").emit();
                 }),
 
             ast::ItemKind::Fn(..) => {
@@ -450,7 +450,9 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast
                 FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
                 FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
             };
-            self.report_unsafe(cx, span, |lint| lint.build(msg).emit());
+            self.report_unsafe(cx, span, |lint| {
+                lint.build(msg).emit();
+            });
         }
     }
 }
@@ -559,7 +561,7 @@ fn check_missing_docs_attrs(
                 MISSING_DOCS,
                 cx.tcx.sess.source_map().guess_head_span(sp),
                 |lint| {
-                    lint.build(&format!("missing documentation for {} {}", article, desc)).emit()
+                    lint.build(&format!("missing documentation for {} {}", article, desc)).emit();
                 },
             );
         }
@@ -777,7 +779,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
                     "type could implement `Copy`; consider adding `impl \
                           Copy`",
                 )
-                .emit()
+                .emit();
             })
         }
     }
@@ -858,7 +860,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
                      or a manual implementation",
                     cx.tcx.def_path_str(debug)
                 ))
-                .emit()
+                .emit();
             });
         }
     }
@@ -1278,7 +1280,9 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
             if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
                 let msg = "transmuting &T to &mut T is undefined behavior, \
                     even if the reference is unused, consider instead using an UnsafeCell";
-                cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit());
+                cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
+                    lint.build(msg).emit();
+                });
             }
         }
 
@@ -1328,7 +1332,7 @@ fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
             if let Some(items) = attr.meta_item_list() {
                 for item in items {
                     cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
-                        lint.build("unstable feature").emit()
+                        lint.build("unstable feature").emit();
                     });
                 }
             }
@@ -1680,7 +1684,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                                 or lifetime parameters",
                             predicate_kind_name, predicate
                         ))
-                        .emit()
+                        .emit();
                     });
                 }
             }
@@ -1915,7 +1919,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
         let attrs = cx.tcx.hir().attrs(it.hir_id());
         if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
             cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
-                lint.build("cannot test inner items").emit()
+                lint.build("cannot test inner items").emit();
             });
         }
     }
@@ -2040,7 +2044,7 @@ fn check_ident_token(
                     format!("r#{}", ident),
                     Applicability::MachineApplicable,
                 )
-                .emit()
+                .emit();
         });
     }
 }
@@ -3055,7 +3059,7 @@ fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignI
                                 "this signature doesn't match the previous declaration",
                             )
                             .note_expected_found(&"", expected_str, &"", found_str)
-                            .emit()
+                            .emit();
                         },
                     );
                 }
index d3c019ad70e3cf598f319ebb52c464134cde2b2b..882fa4496ca26b1438d4c2eb162c70a4d9a31e1b 100644 (file)
@@ -593,7 +593,7 @@ fn lookup_with_diagnostics(
         &self,
         lint: &'static Lint,
         span: Option<impl Into<MultiSpan>>,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
         diagnostic: BuiltinLintDiagnostics,
     ) {
         self.lookup(lint, span, |lint| {
@@ -840,19 +840,23 @@ fn lookup<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
         span: Option<S>,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     );
 
     fn struct_span_lint<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
         span: S,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         self.lookup(lint, Some(span), decorate);
     }
     /// Emit a lint at the appropriate level, with no associated span.
-    fn lint(&self, lint: &'static Lint, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) {
+    fn lint(
+        &self,
+        lint: &'static Lint,
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+    ) {
         self.lookup(lint, None as Option<Span>, decorate);
     }
 }
@@ -893,7 +897,7 @@ fn lookup<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
         span: Option<S>,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         let hir_id = self.last_node_with_lint_attrs;
 
@@ -920,7 +924,7 @@ fn lookup<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
         span: Option<S>,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
     }
index e9b7620bf1d7f50744eb66a3c026874629519887..7447f9f64b7b100f9a8aec19c883ef6d0a2a2145 100644 (file)
@@ -45,7 +45,9 @@ fn check_id(&mut self, id: ast::NodeId) {
             self.context.lookup_with_diagnostics(
                 lint_id.lint,
                 Some(span),
-                |lint| lint.build(&msg).emit(),
+                |lint| {
+                    lint.build(&msg).emit();
+                },
                 diagnostic,
             );
         }
index 0d790e38206084918c7275ee1cddbb5835a0609e..99a5720832e88b35995703d192c3e372fd98c81a 100644 (file)
@@ -652,7 +652,7 @@ pub fn struct_lint(
         &self,
         lint: &'static Lint,
         span: Option<MultiSpan>,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         let (level, src) = self.lint_level(lint);
         struct_lint_level(self.sess, lint, level, src, span, decorate)
index 264a80339ccdb087a667a20ede61303bbc2a184c..6182d2b10ed5b183e6a9d4b295bb061a0fd26de5 100644 (file)
@@ -180,13 +180,13 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
             }
             has_non_ascii_idents = true;
             cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
-                lint.build("identifier contains non-ASCII characters").emit()
+                lint.build("identifier contains non-ASCII characters").emit();
             });
             if check_uncommon_codepoints
                 && !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
             {
                 cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
-                    lint.build("identifier contains uncommon Unicode codepoints").emit()
+                    lint.build("identifier contains uncommon Unicode codepoints").emit();
                 })
             }
         }
@@ -337,7 +337,7 @@ enum ScriptSetUsage {
                             let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
                             note += &char_info;
                         }
-                        lint.build(&message).note(&note).note("please recheck to make sure their usages are indeed what you want").emit()
+                        lint.build(&message).note(&note).note("please recheck to make sure their usages are indeed what you want").emit();
                     });
                 }
             }
index 39b5b7afdaef1dbf4c4e2fc019559afbe9dd00f3..5d734fd2ba7052f40ce51164f72ef082cd9ad521 100644 (file)
@@ -102,7 +102,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             let method = &call.ident.name;
             let message =
                 format!("call to `.{}()` on a reference in this situation does nothing", &method,);
-            lint.build(&message).span_label(span, "unnecessary method call").note(&note).emit()
+            lint.build(&message).span_label(span, "unnecessary method call").note(&note).emit();
         });
     }
 }
index 4c7f3482776d7ff332b562ad840c1e84043a7178..5b6997bf0eeaffafc6294741e8174f9cf638bba5 100644 (file)
@@ -113,7 +113,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                         predicate,
                         cx.tcx.def_path_str(needs_drop)
                     );
-                    lint.build(&msg).emit()
+                    lint.build(&msg).emit();
                 });
             }
         }
@@ -135,7 +135,7 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
                         instead using `{}` to detect whether a type is trivially dropped",
                         cx.tcx.def_path_str(needs_drop)
                     );
-                    lint.build(&msg).emit()
+                    lint.build(&msg).emit();
                 });
             }
         }
index ed5578c754dd55c942e96f4e2db5bbc2dcef358b..c95905b9b185129476566438b1bfc8903d304609 100644 (file)
@@ -441,7 +441,7 @@ fn lint_uint_literal<'tcx>(
                     min,
                     max,
                 ))
-                .emit()
+                .emit();
         });
     }
 }
@@ -502,7 +502,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::Binary(binop, ref l, ref r) => {
                 if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
                     cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
-                        lint.build("comparison is useless due to type limits").emit()
+                        lint.build("comparison is useless due to type limits").emit();
                     });
                 }
             }
@@ -1382,7 +1382,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
                                           larger ({} bytes) than the next largest",
                             largest
                         ))
-                        .emit()
+                        .emit();
                     },
                 );
             }
index abe34a8a39f1470699f3dcd23cc6625b59b5b9db..91b72f1d2b17ead0cd9a8e7412fc1364c8a1e001 100644 (file)
@@ -170,7 +170,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
 
         if !(type_permits_lack_of_use || fn_warned || op_warned) {
             cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
-                lint.build(&format!("unused result of type `{}`", ty)).emit()
+                lint.build(&format!("unused result of type `{}`", ty)).emit();
             });
         }
 
@@ -368,9 +368,9 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
                         } else {
                             lint.span_help(s.span, "use `drop` to clarify the intent");
                         }
-                        lint.emit()
+                        lint.emit();
                     } else {
-                        lint.build("path statement with no effect").emit()
+                        lint.build("path statement with no effect").emit();
                     }
                 });
             }
@@ -1111,7 +1111,7 @@ fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &
             };
 
             cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
-                lint.build(&format!("braces around {} is unnecessary", node_name)).emit()
+                lint.build(&format!("braces around {} is unnecessary", node_name)).emit();
             });
         }
     }
@@ -1170,7 +1170,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
                             "unnecessary allocation, use `&mut` instead"
                         }
                     };
-                    lint.build(msg).emit()
+                    lint.build(msg).emit();
                 });
             }
         }
index f667aec03c577f438c5b037d585367d4c42772f6..a9e3b55aeeedfa4f1ccf83d29a618c6c593adccc 100644 (file)
@@ -825,11 +825,13 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         for (_, data) in self.cstore.iter_crate_data() {
             if data.has_global_allocator() {
                 match global_allocator {
-                    Some(other_crate) => self.sess.err(&format!(
+                    Some(other_crate) => {
+                        self.sess.err(&format!(
                         "the `#[global_allocator]` in {} conflicts with global allocator in: {}",
                         other_crate,
                         data.name()
-                    )),
+                    ));
+                    }
                     None => global_allocator = Some(data.name()),
                 }
             }
@@ -864,7 +866,7 @@ fn inject_dependency_if(
         // 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.sess.has_errors() {
+        if self.sess.has_errors().is_some() {
             return;
         }
 
index f4bc28f4da19914ee396fcb465356c030160e3da..c3a7611239139ecae963b0ce41aac746b78e8be4 100644 (file)
@@ -145,41 +145,49 @@ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
                             ("bundle", NativeLibKind::Static { bundle, .. }) => {
                                 *bundle = Some(value);
                             }
-                            ("bundle", _) => sess.span_err(
-                                span,
-                                "bundle linking modifier is only compatible with \
+                            ("bundle", _) => {
+                                sess.span_err(
+                                    span,
+                                    "bundle linking modifier is only compatible with \
                                 `static` linking kind",
-                            ),
+                                );
+                            }
 
                             ("verbatim", _) => lib.verbatim = Some(value),
 
                             ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
                                 *whole_archive = Some(value);
                             }
-                            ("whole-archive", _) => sess.span_err(
-                                span,
-                                "whole-archive linking modifier is only compatible with \
+                            ("whole-archive", _) => {
+                                sess.span_err(
+                                    span,
+                                    "whole-archive linking modifier is only compatible with \
                                 `static` linking kind",
-                            ),
+                                );
+                            }
 
                             ("as-needed", NativeLibKind::Dylib { as_needed })
                             | ("as-needed", NativeLibKind::Framework { as_needed }) => {
                                 *as_needed = Some(value);
                             }
-                            ("as-needed", _) => sess.span_err(
-                                span,
-                                "as-needed linking modifier is only compatible with \
+                            ("as-needed", _) => {
+                                sess.span_err(
+                                    span,
+                                    "as-needed linking modifier is only compatible with \
                                 `dylib` and `framework` linking kinds",
-                            ),
+                                );
+                            }
 
-                            _ => sess.span_err(
-                                span,
-                                &format!(
-                                    "unrecognized linking modifier `{}`, expected one \
+                            _ => {
+                                sess.span_err(
+                                    span,
+                                    &format!(
+                                        "unrecognized linking modifier `{}`, expected one \
                                     of: bundle, verbatim, whole-archive, as-needed",
-                                    modifier
-                                ),
-                            ),
+                                        modifier
+                                    ),
+                                );
+                            }
                         }
                     }
                 } else {
@@ -247,7 +255,9 @@ fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
                 Some(span) => {
                     struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit();
                 }
-                None => self.tcx.sess.err(msg),
+                None => {
+                    self.tcx.sess.err(msg);
+                }
             }
         }
         if lib.cfg.is_some() && !self.tcx.features().link_cfg {
index 1b301629b9c73ac37fb15fd7fe2c66cd003a45e4..dc1fe5f2b0836d947352eb7f21e941bc69114db4 100644 (file)
@@ -2,7 +2,9 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId};
+use rustc_errors::{
+    Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed,
+};
 use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
 use rustc_query_system::ich::StableHashingContext;
@@ -220,22 +222,28 @@ pub fn new(
     }
 }
 
-pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a, ()>);
+pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
 
-impl<'a> LintDiagnosticBuilder<'a> {
-    /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
-    pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, ()> {
+impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
+    /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
+    pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, G> {
         self.0.set_primary_message(msg);
         self.0.set_is_lint();
         self.0
     }
 
-    /// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder.
-    pub fn new(err: DiagnosticBuilder<'a, ()>) -> LintDiagnosticBuilder<'a> {
+    /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
+    pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
         LintDiagnosticBuilder(err)
     }
 }
 
+impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
+    pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
+        LintDiagnosticBuilder(self.0.forget_guarantee())
+    }
+}
+
 pub fn explain_lint_level_source(
     sess: &Session,
     lint: &'static Lint,
@@ -316,7 +324,7 @@ pub fn struct_lint_level<'s, 'd>(
     level: Level,
     src: LintLevelSource,
     span: Option<MultiSpan>,
-    decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + 'd,
+    decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) + 'd,
 ) {
     // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
     // the "real" work.
@@ -326,7 +334,7 @@ fn struct_lint_level_impl<'s, 'd>(
         level: Level,
         src: LintLevelSource,
         span: Option<MultiSpan>,
-        decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>,
+        decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) + 'd>,
     ) {
         // Check for future incompatibility lints and issue a stronger warning.
         let future_incompatible = lint.future_incompatible;
index 167a097d9f8523b90d720e70b4eb1a803eb52598..219af6caa1ae1943d6726a406340a943b45ba42d 100644 (file)
@@ -258,7 +258,7 @@ fn late_report_deprecation(
             let kind = tcx.def_kind(def_id).descr(def_id);
             deprecation_suggestion(&mut diag, kind, suggestion, method_span);
         }
-        diag.emit()
+        diag.emit();
     });
 }
 
@@ -483,7 +483,7 @@ pub fn check_optional_stability(
     ) {
         let soft_handler = |lint, span, msg: &_| {
             self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
-                lint.build(msg).emit()
+                lint.build(msg).emit();
             })
         };
         match self.eval_stability(def_id, id, span, method_span) {
index 2c3c61259c473b604587a8a6efb2811fe4440fc2..492091a4f25405f5ed1a47161e8fda432e5752cf 100644 (file)
@@ -91,7 +91,7 @@ fn print_backtrace(backtrace: &Backtrace) {
 impl From<ErrorHandled> for InterpErrorInfo<'_> {
     fn from(err: ErrorHandled) -> Self {
         match err {
-            ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {
+            ErrorHandled::Reported(ErrorGuaranteed { .. }) | ErrorHandled::Linted => {
                 err_inval!(ReferencedConstant)
             }
             ErrorHandled::TooGeneric => err_inval!(TooGeneric),
@@ -160,7 +160,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             TooGeneric => write!(f, "encountered overly generic constant"),
             ReferencedConstant => write!(f, "referenced constant has errors"),
-            AlreadyReported(ErrorGuaranteed) => {
+            AlreadyReported(ErrorGuaranteed { .. }) => {
                 write!(f, "encountered constants with type errors, stopping evaluation")
             }
             Layout(ref err) => write!(f, "{}", err),
index 44b622c1e3d86dfad26fb2af5a9b2ea603d34ad3..e07b174bc6aaa3cec64da30129f898697391da03 100644 (file)
     }
 
     /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
-    query thir_body(key: ty::WithOptConstParam<LocalDefId>) -> (&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId) {
+    query thir_body(key: ty::WithOptConstParam<LocalDefId>)
+        -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed>
+    {
         // Perf tests revealed that hashing THIR is inefficient (see #85729).
         no_hash
         desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
index 4ff8e61ee743758c8b15bcb6d1e9bb96944f7949..c43ec048c3f99e2e086ac0c541229d20de268f66 100644 (file)
@@ -31,12 +31,12 @@ pub struct Graph {
     pub children: DefIdMap<Children>,
 
     /// Whether an error was emitted while constructing the graph.
-    pub has_errored: bool,
+    pub has_errored: Option<ErrorGuaranteed>,
 }
 
 impl Graph {
     pub fn new() -> Graph {
-        Graph { parent: Default::default(), children: Default::default(), has_errored: false }
+        Graph { parent: Default::default(), children: Default::default(), has_errored: None }
     }
 
     /// The parent of a given impl, which is the `DefId` of the trait when the
@@ -246,8 +246,10 @@ pub fn ancestors<'tcx>(
 ) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
 
-    if specialization_graph.has_errored || tcx.type_of(start_from_impl).references_error() {
-        Err(ErrorGuaranteed)
+    if let Some(reported) = specialization_graph.has_errored {
+        Err(reported)
+    } else if let Some(reported) = tcx.type_of(start_from_impl).error_reported() {
+        Err(reported)
     } else {
         Ok(Ancestors {
             trait_def_id,
index cad77f6436ea26fe463beb7a34533ab043831b64..cb219c4c4e4c9a1b5e394afafa1859f435f670a0 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::HashingControls;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -453,7 +452,7 @@ pub fn eval_explicit_discr(self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<D
             }
             Err(err) => {
                 let msg = match err {
-                    ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {
+                    ErrorHandled::Reported(_) | ErrorHandled::Linted => {
                         "enum discriminant evaluation failed"
                     }
                     ErrorHandled::TooGeneric => "enum discriminant depends on generics",
index e72828dd529593139c504acec20655e856c48a7a..4b7c1d44cea29f6c6a531fd8519720e9e9eb836d 100644 (file)
@@ -264,7 +264,7 @@ pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
         if let Some(val) = self.val().try_eval(tcx, param_env) {
             match val {
                 Ok(val) => Const::from_value(tcx, val, self.ty()),
-                Err(ErrorGuaranteed) => tcx.const_error(self.ty()),
+                Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
             }
         } else {
             self
index 494535f3d597ac1ca294ce2599cd6f322ccbe6e7..f51e6c2bc1f4d53736da680bd25bd8096a0f57c2 100644 (file)
@@ -91,7 +91,10 @@ fn new_empty(source_map: &'tcx SourceMap) -> Self
 /// except through the error-reporting functions on a [`tcx`][TyCtxt].
 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
 #[derive(TyEncodable, TyDecodable, HashStable)]
-pub struct DelaySpanBugEmitted(());
+pub struct DelaySpanBugEmitted {
+    pub reported: ErrorGuaranteed,
+    _priv: (),
+}
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
 
@@ -1236,8 +1239,8 @@ pub fn ty_error(self) -> Ty<'tcx> {
     /// ensure it gets used.
     #[track_caller]
     pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
-        self.sess.delay_span_bug(span, msg);
-        self.mk_ty(Error(DelaySpanBugEmitted(())))
+        let reported = self.sess.delay_span_bug(span, msg);
+        self.mk_ty(Error(DelaySpanBugEmitted { reported, _priv: () }))
     }
 
     /// Like [TyCtxt::ty_error] but for constants.
@@ -1258,8 +1261,11 @@ pub fn const_error_with_message<S: Into<MultiSpan>>(
         span: S,
         msg: &str,
     ) -> Const<'tcx> {
-        self.sess.delay_span_bug(span, msg);
-        self.mk_const(ty::ConstS { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
+        let reported = self.sess.delay_span_bug(span, msg);
+        self.mk_const(ty::ConstS {
+            val: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }),
+            ty,
+        })
     }
 
     pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
@@ -2733,7 +2739,7 @@ pub fn struct_span_lint_hir(
         lint: &'static Lint,
         hir_id: HirId,
         span: impl Into<MultiSpan>,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         let (level, src) = self.lint_level_at_node(lint, hir_id);
         struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
@@ -2743,7 +2749,7 @@ pub fn struct_lint_node(
         self,
         lint: &'static Lint,
         id: HirId,
-        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
+        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
     ) {
         let (level, src) = self.lint_level_at_node(lint, id);
         struct_lint_level(self.sess, lint, level, src, None, decorate);
index 4922d07ae1c5da22d649fddf7c546381db0ebfc8..780d380da365eceab5a4cdc1504fb95229f4965d 100644 (file)
@@ -51,6 +51,7 @@
 //! ```
 use crate::mir;
 use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::FxHashSet;
@@ -151,6 +152,13 @@ fn has_opaque_types(&self) -> bool {
     fn references_error(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_ERROR)
     }
+    fn error_reported(&self) -> Option<ErrorGuaranteed> {
+        if self.references_error() {
+            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+        } else {
+            None
+        }
+    }
     fn has_param_types_or_consts(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
     }
index e12d075efa9b603a9c77ae4b5c774c49ffaaa62c..ab3dc8f020cc9ec2878900e4249169ec15620032 100644 (file)
@@ -118,7 +118,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
             };
 
             let body = tcx.hir().body(body_id);
-            let (thir, expr) = tcx.thir_body(def);
+            let (thir, expr) = tcx
+                .thir_body(def)
+                .unwrap_or_else(|_| (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)));
             // We ran all queries that depended on THIR at the beginning
             // of `mir_build`, so now we can steal it
             let thir = thir.steal();
@@ -229,7 +231,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
 
             let return_ty = typeck_results.node_type(id);
 
-            let (thir, expr) = tcx.thir_body(def);
+            let (thir, expr) = tcx
+                .thir_body(def)
+                .unwrap_or_else(|_| (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)));
             // We ran all queries that depended on THIR at the beginning
             // of `mir_build`, so now we can steal it
             let thir = thir.steal();
index a96bb4e03d97ae81b5193f00f8cb5d24696f2f43..122af3f621087122a2f2e1d7deeb2756952d8330 100644 (file)
@@ -405,7 +405,9 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 } else {
                     ty::WithOptConstParam::unknown(closure_id)
                 };
-                let (closure_thir, expr) = self.tcx.thir_body(closure_def);
+                let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
+                    (self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
+                });
                 let closure_thir = &closure_thir.borrow();
                 let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
                 let mut closure_visitor =
@@ -606,7 +608,10 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         return;
     }
 
-    let (thir, expr) = tcx.thir_body(def);
+    let (thir, expr) = match tcx.thir_body(def) {
+        Ok(body) => body,
+        Err(_) => return,
+    };
     let thir = &thir.borrow();
     // If `thir` is empty, a type error occurred, skip this body.
     if thir.exprs.is_empty() {
index a65a3ed31f638c8536edd79c8188c64ec3e39d8d..426596bf13c0a6a6ac69e8b1e137f4b854c2dbb2 100644 (file)
@@ -7,6 +7,7 @@
 
 use rustc_ast as ast;
 use rustc_data_structures::steal::Steal;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::HirId;
 crate fn thir_body<'tcx>(
     tcx: TyCtxt<'tcx>,
     owner_def: ty::WithOptConstParam<LocalDefId>,
-) -> (&'tcx Steal<Thir<'tcx>>, ExprId) {
+) -> Result<(&'tcx Steal<Thir<'tcx>>, ExprId), ErrorGuaranteed> {
     let hir = tcx.hir();
     let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did)));
     let mut cx = Cx::new(tcx, owner_def);
-    if cx.typeck_results.tainted_by_errors.is_some() {
-        return (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0));
+    if let Some(reported) = cx.typeck_results.tainted_by_errors {
+        return Err(reported);
     }
     let expr = cx.mirror_expr(&body.value);
-    (tcx.alloc_steal_thir(cx.thir), expr)
+    Ok((tcx.alloc_steal_thir(cx.thir), expr))
 }
 
 crate fn thir_tree<'tcx>(
     tcx: TyCtxt<'tcx>,
     owner_def: ty::WithOptConstParam<LocalDefId>,
 ) -> String {
-    format!("{:#?}", thir_body(tcx, owner_def).0.steal())
+    match thir_body(tcx, owner_def) {
+        Ok((thir, _)) => format!("{:#?}", thir.steal()),
+        Err(_) => "error".into(),
+    }
 }
 
 struct Cx<'tcx> {
index ae9b44cee4bf8fe07dbf803c20fe3a28b1720a91..dd7d4e3e514cdd2d485ad2e24ec506af0185b46e 100644 (file)
@@ -194,7 +194,9 @@ fn to_pat(&mut self, cv: ty::Const<'tcx>, mir_structural_match_violation: bool)
                         lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                         self.id,
                         self.span,
-                        |lint| lint.build(&msg).emit(),
+                        |lint| {
+                            lint.build(&msg).emit();
+                        },
                     );
                 } else {
                     debug!(
@@ -272,7 +274,9 @@ fn recur(
                         lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                         id,
                         span,
-                        |lint| lint.build("floating-point types cannot be used in patterns").emit(),
+                        |lint| {
+                            lint.build("floating-point types cannot be used in patterns").emit();
+                        },
                     );
                 }
                 PatKind::Constant { value: cv }
@@ -284,7 +288,7 @@ fn recur(
                 if self.include_lint_checks {
                     tcx.sess.span_err(span, msg);
                 } else {
-                    tcx.sess.delay_span_bug(span, msg)
+                    tcx.sess.delay_span_bug(span, msg);
                 }
                 PatKind::Wild
             }
@@ -301,7 +305,7 @@ fn recur(
                 if self.include_lint_checks {
                     tcx.sess.span_err(self.span, &msg);
                 } else {
-                    tcx.sess.delay_span_bug(self.span, &msg)
+                    tcx.sess.delay_span_bug(self.span, &msg);
                 }
                 PatKind::Wild
             }
@@ -331,7 +335,7 @@ fn recur(
                                 cv.ty(),
                                 cv.ty(),
                             );
-                            lint.build(&msg).emit()
+                            lint.build(&msg).emit();
                         },
                     );
                 }
@@ -356,7 +360,7 @@ fn recur(
                 if self.include_lint_checks {
                     tcx.sess.span_err(span, &msg);
                 } else {
-                    tcx.sess.delay_span_bug(span, &msg)
+                    tcx.sess.delay_span_bug(span, &msg);
                 }
                 PatKind::Wild
             }
@@ -393,7 +397,7 @@ fn recur(
                     if self.include_lint_checks {
                         tcx.sess.span_err(span, &msg);
                     } else {
-                        tcx.sess.delay_span_bug(span, &msg)
+                        tcx.sess.delay_span_bug(span, &msg);
                     }
                     PatKind::Wild
                 }
@@ -471,7 +475,7 @@ fn recur(
                                 lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                                 self.id,
                                 self.span,
-                                |lint| lint.build(&msg).emit(),
+                                |lint| {lint.build(&msg).emit();},
                             );
                         }
                         PatKind::Constant { value: cv }
@@ -482,7 +486,7 @@ fn recur(
                             if self.include_lint_checks {
                                 tcx.sess.span_err(span, &msg);
                             } else {
-                                tcx.sess.delay_span_bug(span, &msg)
+                                tcx.sess.delay_span_bug(span, &msg);
                             }
                         }
                         PatKind::Wild
@@ -539,7 +543,9 @@ fn recur(
                         lint::builtin::POINTER_STRUCTURAL_MATCH,
                         id,
                         span,
-                        |lint| lint.build(&msg).emit(),
+                        |lint| {
+                            lint.build(&msg).emit();
+                        },
                     );
                 }
                 PatKind::Constant { value: cv }
@@ -550,7 +556,7 @@ fn recur(
                 if self.include_lint_checks {
                     tcx.sess.span_err(span, &msg);
                 } else {
-                    tcx.sess.delay_span_bug(span, &msg)
+                    tcx.sess.delay_span_bug(span, &msg);
                 }
                 PatKind::Wild
             }
@@ -575,7 +581,9 @@ fn recur(
                 lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
                 id,
                 span,
-                |lint| lint.build(&msg).emit(),
+                |lint| {
+                    lint.build(&msg).emit();
+                },
             );
         }
 
index 8731669b10958cae895d4ed66593b20f76e7cfbc..097a6186cd57a85d97b31ad9c926f9681e322938 100644 (file)
@@ -64,7 +64,7 @@ fn lint_const_item_usage(
         place: &Place<'tcx>,
         const_item: DefId,
         location: Location,
-        decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b, ()>,
+        decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) -> DiagnosticBuilder<'b, ()>,
     ) {
         // Don't lint on borrowing/assigning when a dereference is involved.
         // If we 'leave' the temporary via a dereference, we must
@@ -88,7 +88,7 @@ fn lint_const_item_usage(
                 |lint| {
                     decorate(lint)
                         .span_note(self.tcx.def_span(const_item), "`const` item defined here")
-                        .emit()
+                        .emit();
                 },
             );
         }
index 23d59c8007135c0b91ba9031a28c19d87e7f190a..f0367958ef8c5e4e7f82cad7916cd245f0296083 100644 (file)
@@ -46,7 +46,7 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
              does not derive Copy (error E0133)"
                 .to_string()
         };
-        lint.build(&message).emit()
+        lint.build(&message).emit();
     });
 }
 
@@ -110,7 +110,7 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location:
                                     reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
                                     (loads and stores via `*p` must be properly aligned even when using raw pointers)"
                                 )
-                                .emit()
+                                .emit();
                         },
                     );
                 }
index 34c539f319194761c161ca96b6e6c372a9a3e8ec..5ed33ab9fec17bf0d6a1b2a8ca086f5e313b5040 100644 (file)
@@ -538,7 +538,7 @@ fn report_assert_as_lint(
             self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
                 let mut err = lint.build(message);
                 err.span_label(source_info.span, format!("{:?}", panic));
-                err.emit()
+                err.emit();
             });
         }
     }
index ed771534c4c4c2c152252541c294998261dcc65d..a9dcc484b9e8de0f553e57b3977833c56aa79b8e 100644 (file)
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
-use rustc_errors::{ErrorGuaranteed, FatalError};
+use rustc_errors::FatalError;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -716,9 +716,7 @@ fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location)
                     match self.tcx.const_eval_resolve(param_env, ct, None) {
                         // The `monomorphize` call should have evaluated that constant already.
                         Ok(val) => val,
-                        Err(ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted) => {
-                            return;
-                        }
+                        Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
                         Err(ErrorHandled::TooGeneric) => span_bug!(
                             self.body.source_info(location).span,
                             "collection encountered polymorphic constant: {:?}",
@@ -750,7 +748,7 @@ fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
                         substituted_constant,
                         val
                     ),
-                    Err(ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted) => {}
+                    Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => {}
                     Err(ErrorHandled::TooGeneric) => span_bug!(
                         self.body.source_info(location).span,
                         "collection encountered polymorphic constant: {}",
@@ -864,7 +862,7 @@ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
                     |lint| {
                         let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
                         err.span_label(source_info.span, "value moved from here");
-                        err.emit()
+                        err.emit();
                     },
                 );
             }
index c7d166319eac8621af1a56109eb99ab1ac4f52c5..bec4561928cc259081ec91a482126e0b48702040 100644 (file)
@@ -202,7 +202,7 @@ pub(crate) fn emit_unescape_error(
             diag.emit();
         }
         EscapeError::TooShortHexEscape => {
-            handler.span_err(span, "numeric character escape is too short")
+            handler.span_err(span, "numeric character escape is too short");
         }
         EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
             let (c, span) = last_char();
index b582f060395c38c9c9994ca9cf5daadebaef46d6..4d5c552b81bb17eb20514ae20b2d1d4e25a9465d 100644 (file)
@@ -212,10 +212,10 @@ fn parse_item_kind(
             if let Err(mut e) = self.expect_semi() {
                 match tree.kind {
                     UseTreeKind::Glob => {
-                        e.note("the wildcard token must be last on the path").emit();
+                        e.note("the wildcard token must be last on the path");
                     }
                     UseTreeKind::Nested(..) => {
-                        e.note("glob-like brace syntax must be last on the path").emit();
+                        e.note("glob-like brace syntax must be last on the path");
                     }
                     _ => (),
                 }
@@ -1485,7 +1485,7 @@ fn parse_single_struct_field(
                     // Make sure an error was emitted (either by recovering an angle bracket,
                     // or by finding an identifier as the next token), since we're
                     // going to continue parsing
-                    assert!(self.sess.span_diagnostic.has_errors());
+                    assert!(self.sess.span_diagnostic.has_errors().is_some());
                 } else {
                     return Err(err);
                 }
index 06184b4797255a7f98855ea2269990b5bfc66dad..ebf6678d3ad37f7a5dc5ba644b685cc687a056ce 100644 (file)
@@ -169,7 +169,7 @@ fn check_attributes(
                             }
                             ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
                         };
-                        lint.build(msg).emit()
+                        lint.build(msg).emit();
                     });
                 }
             }
@@ -236,7 +236,7 @@ fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targ
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
             Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
                 self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
-                    lint.build("`#[inline]` is ignored on function prototypes").emit()
+                    lint.build("`#[inline]` is ignored on function prototypes").emit();
                 });
                 true
             }
index ea99a90e937c39a9a292bd1d08c85900e79a2ed3..7298aba7e8763ddf4be9295dacf8e8fafd430f8e 100644 (file)
@@ -1588,7 +1588,7 @@ fn report_unused(
                                 shorthands,
                                 Applicability::MachineApplicable,
                             );
-                            err.emit()
+                            err.emit();
                         },
                     );
                 } else {
@@ -1611,7 +1611,7 @@ fn report_unused(
                                 non_shorthands,
                                 Applicability::MachineApplicable,
                             );
-                            err.emit()
+                            err.emit();
                         },
                     );
                 }
index f36a1f61aaccb03f02d693a14480a9491567dce2..09be1dac6f1638e33abbfd353a477492cb03b656 100644 (file)
@@ -128,7 +128,7 @@ fn annotate<F>(
                             String::new(),
                             rustc_errors::Applicability::MachineApplicable,
                         )
-                        .emit()
+                        .emit();
                 });
             }
 
@@ -728,10 +728,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                                 INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
                                 item.hir_id(),
                                 span,
-                                |lint| lint
+                                |lint| {lint
                                     .build("an `#[unstable]` annotation here has no effect")
                                     .note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
-                                    .emit()
+                                    .emit();}
                             );
                         }
                     }
index fdda77d01b3febd8d4e31bea13d516dd5561d1ab..1f286d557ca0baf5dfdae0138e4c92d802e1a575 100644 (file)
@@ -1742,7 +1742,7 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
                         descr,
                         self.tcx.crate_name(def_id.krate)
                     ))
-                    .emit()
+                    .emit();
                 },
             );
         }
@@ -1786,7 +1786,9 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
                     lint::builtin::PRIVATE_IN_PUBLIC,
                     hir_id,
                     span,
-                    |lint| lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(),
+                    |lint| {
+                        lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
+                    },
                 );
             }
         }
index 8dec28c8ae283bef8913b1d496bc401bc73a199b..1394f4083d0b9a1c4b58d347688e64a4ffe0860f 100644 (file)
@@ -1997,7 +1997,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     Vec::new(),
                     &[],
                 );
-                db.emit()
+                db.emit();
             },
         );
     }
index 1997f2133ed0020debe30cfe0c61774f1860eb40..7e743481a51fcaefa991d556a6f2a4347788437b 100644 (file)
@@ -3143,10 +3143,12 @@ fn check_lifetime_params(
             for bound in lifetime_i.bounds {
                 match bound {
                     hir::GenericBound::Outlives(ref lt) => match lt.name {
-                        hir::LifetimeName::Underscore => self.tcx.sess.delay_span_bug(
-                            lt.span,
-                            "use of `'_` in illegal place, but not caught by lowering",
-                        ),
+                        hir::LifetimeName::Underscore => {
+                            self.tcx.sess.delay_span_bug(
+                                lt.span,
+                                "use of `'_` in illegal place, but not caught by lowering",
+                            );
+                        }
                         hir::LifetimeName::Static => {
                             self.insert_lifetime(lt, Region::Static);
                             self.tcx
@@ -3172,7 +3174,7 @@ fn check_lifetime_params(
                                 lt.span,
                                 "lowering generated `ImplicitObjectLifetimeDefault` \
                                  outside of an object type",
-                            )
+                            );
                         }
                         hir::LifetimeName::Error => {
                             // No need to do anything, error already reported.
index bca19e84cf87579b626f2a2deaa60ca540b8398f..7f696da86f20ea54eac2c356f7051ec4707792ce 100644 (file)
@@ -100,7 +100,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
             match sp {
                 Some(sp) => sess.span_err(sp, s),
                 None => sess.err(s),
-            }
+            };
             err_count += 1;
         };
         if s.is_empty() {
index eabebfcf3eae5145c17133b636d54596ab4f8a84..7eeb6f90f99d9e5578ccbb39ba7bb3fbece00727 100644 (file)
@@ -262,7 +262,7 @@ fn check_miri_unleashed_features(&self) {
             }
             diag.emit();
             // If we should err, make sure we did.
-            if must_err && !self.has_errors() {
+            if must_err && !self.has_errors().is_some() {
                 // We have skipped a feature gate, and not run into other errors... reject.
                 self.err(
                     "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \
@@ -404,13 +404,13 @@ pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg:
             self.span_err(sp, msg);
         }
     }
-    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed {
         self.diagnostic().span_err(sp, msg)
     }
     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.diagnostic().span_err_with_code(sp, &msg, code)
     }
-    pub fn err(&self, msg: &str) {
+    pub fn err(&self, msg: &str) -> ErrorGuaranteed {
         self.diagnostic().err(msg)
     }
     pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
@@ -420,7 +420,7 @@ pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuarantee
     pub fn err_count(&self) -> usize {
         self.diagnostic().err_count()
     }
-    pub fn has_errors(&self) -> bool {
+    pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
         self.diagnostic().has_errors()
     }
     pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
@@ -430,9 +430,9 @@ pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
     pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
-        if self.diagnostic().has_errors_or_lint_errors() {
-            self.diagnostic().emit_stashed_diagnostics();
-            Err(ErrorGuaranteed)
+        if let Some(reported) = self.diagnostic().has_errors_or_lint_errors() {
+            let _ = self.diagnostic().emit_stashed_diagnostics();
+            Err(reported)
         } else {
             Ok(())
         }
@@ -444,7 +444,11 @@ pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorGuaranteed>
     {
         let old_count = self.err_count();
         let result = f();
-        if self.err_count() == old_count { Ok(result) } else { Err(ErrorGuaranteed) }
+        if self.err_count() == old_count {
+            Ok(result)
+        } else {
+            Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+        }
     }
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().span_warn(sp, msg)
@@ -457,7 +461,7 @@ pub fn warn(&self, msg: &str) {
     }
     /// Delay a span_bug() call until abort_if_errors()
     #[track_caller]
-    pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed {
         self.diagnostic().delay_span_bug(sp, msg)
     }
 
@@ -1387,12 +1391,18 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
     match unsupported_sanitizers.into_iter().count() {
         0 => {}
-        1 => sess
-            .err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
-        _ => sess.err(&format!(
-            "{} sanitizers are not supported for this target",
-            unsupported_sanitizers
-        )),
+        1 => {
+            sess.err(&format!(
+                "{} sanitizer is not supported for this target",
+                unsupported_sanitizers
+            ));
+        }
+        _ => {
+            sess.err(&format!(
+                "{} sanitizers are not supported for this target",
+                unsupported_sanitizers
+            ));
+        }
     }
     // Cannot mix and match sanitizers.
     let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
@@ -1446,7 +1456,7 @@ pub enum IncrCompSession {
     InvalidBecauseOfErrors { session_directory: PathBuf },
 }
 
-pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) {
+pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
     let emitter: Box<dyn Emitter + sync::Send> = match output {
         config::ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -1457,7 +1467,8 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) {
         }
     };
     let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-    handler.struct_fatal(msg).emit();
+    let reported = handler.struct_fatal(msg).emit();
+    reported
 }
 
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
index 3e0c8234edafb21970dd9f59f03860685c58482d..a607fb6c1b87c392c2547ed9f88fed1eddf02939 100644 (file)
@@ -51,7 +51,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
                 // leading to an ambiguous result. So report this as an
                 // overflow bug, since I believe this is the only case
                 // where ambiguity can result.
-                infcx.tcx.sess.delay_span_bug(
+                let reported = infcx.tcx.sess.delay_span_bug(
                     rustc_span::DUMMY_SP,
                     &format!(
                         "encountered ambiguity selecting `{:?}` during codegen, presuming due to \
@@ -59,21 +59,21 @@ pub fn codegen_fulfill_obligation<'tcx>(
                         trait_ref
                     ),
                 );
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
             Err(Unimplemented) => {
                 // This can trigger when we probe for the source of a `'static` lifetime requirement
                 // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
                 // This can also trigger when we have a global bound that is not actually satisfied,
                 // but was included during typeck due to the trivial_bounds feature.
-                infcx.tcx.sess.delay_span_bug(
+                let guar = infcx.tcx.sess.delay_span_bug(
                     rustc_span::DUMMY_SP,
                     &format!(
                         "Encountered error `Unimplemented` selecting `{:?}` during codegen",
                         trait_ref
                     ),
                 );
-                return Err(ErrorGuaranteed);
+                return Err(guar);
             }
             Err(e) => {
                 bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
index f880b28b3c8dc2f12d7b26ca6304ff482190886d..40a39c4cfc2e39564eed2c6cd2f87d4c28eddc84 100644 (file)
@@ -18,7 +18,7 @@
 use rustc_middle::thir;
 use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
 use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, DelaySpanBugEmitted, TyCtxt, TypeFoldable};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
@@ -177,8 +177,9 @@ enum FailureKind {
             false => NotConstEvaluatable::MentionsParam,
         }),
         Err(ErrorHandled::Linted) => {
-            infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
-            Err(NotConstEvaluatable::Error(ErrorGuaranteed))
+            let reported =
+                infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
+            Err(NotConstEvaluatable::Error(reported))
         }
         Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
         Ok(_) => Ok(()),
@@ -244,7 +245,7 @@ pub fn from_const(
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
         match ct.val() {
             ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
-            ty::ConstKind::Error(_) => Err(ErrorGuaranteed),
+            ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
             _ => Ok(None),
         }
     }
@@ -280,17 +281,19 @@ fn root_span(&self) -> Span {
     }
 
     fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
-        self.tcx
+        let reported = self
+            .tcx
             .sess
             .struct_span_err(self.root_span(), "overly complex generic constant")
             .span_label(span, msg)
             .help("consider moving this anonymous constant into a `const` function")
             .emit();
 
-        Err(ErrorGuaranteed)
+        Err(reported)
     }
     fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
-        self.tcx
+        let reported = self
+            .tcx
             .sess
             .struct_span_err(self.root_span(), "overly complex generic constant")
             .span_label(span, msg)
@@ -298,7 +301,7 @@ fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGua
             .note("this operation may be supported in the future")
             .emit();
 
-        Err(ErrorGuaranteed)
+        Err(reported)
     }
 
     fn new(
@@ -553,11 +556,7 @@ pub(super) fn thir_abstract_const<'tcx>(
             _ => return Ok(None),
         }
 
-        let body = tcx.thir_body(def);
-        if body.0.borrow().exprs.is_empty() {
-            // type error in constant, there is no thir
-            return Err(ErrorGuaranteed);
-        }
+        let body = tcx.thir_body(def)?;
 
         AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
             .map(AbstractConstBuilder::build)
@@ -580,7 +579,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
 
         Ok(false)
     })()
-    .unwrap_or_else(|ErrorGuaranteed| true)
+    .unwrap_or_else(|_: ErrorGuaranteed| true)
     // FIXME(generic_const_exprs): We should instead have this
     // method return the resulting `ty::Const` and return `ConstKind::Error`
     // on `ErrorGuaranteed`.
index 55201d17f714d72c2349fa6adfe5ac74d7b415c8..229e108d5d64070322005adec4cd33e4962119ba 100644 (file)
@@ -63,7 +63,7 @@ fn report_fulfillment_errors(
         errors: &[FulfillmentError<'tcx>],
         body_id: Option<hir::BodyId>,
         fallback_has_occurred: bool,
-    );
+    ) -> ErrorGuaranteed;
 
     fn report_overflow_error<T>(
         &self,
@@ -111,7 +111,7 @@ fn report_fulfillment_errors(
         errors: &[FulfillmentError<'tcx>],
         body_id: Option<hir::BodyId>,
         fallback_has_occurred: bool,
-    ) {
+    ) -> ErrorGuaranteed {
         #[derive(Debug)]
         struct ErrorDescriptor<'tcx> {
             predicate: ty::Predicate<'tcx>,
@@ -190,6 +190,8 @@ struct ErrorDescriptor<'tcx> {
                 self.report_fulfillment_error(error, body_id, fallback_has_occurred);
             }
         }
+
+        self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fullfillment errors")
     }
 
     /// Reports that an overflow has occurred and halts compilation. We
@@ -312,7 +314,9 @@ fn report_selection_error(
                         let predicate_is_const = ty::BoundConstness::ConstIfConst
                             == trait_predicate.skip_binder().constness;
 
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                        if self.tcx.sess.has_errors().is_some()
+                            && trait_predicate.references_error()
+                        {
                             return;
                         }
                         let trait_ref = trait_predicate.to_poly_trait_ref();
@@ -919,7 +923,7 @@ fn report_selection_error(
             }
 
             // Already reported in the query.
-            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorGuaranteed)) => {
+            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => {
                 // FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token.
                 self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
                 return;
@@ -1857,7 +1861,7 @@ fn maybe_report_ambiguity(
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
                 if arg.references_error()
-                    || self.tcx.sess.has_errors()
+                    || self.tcx.sess.has_errors().is_some()
                     || self.is_tainted_by_errors()
                 {
                     return;
@@ -1868,7 +1872,7 @@ fn maybe_report_ambiguity(
 
             ty::PredicateKind::Subtype(data) => {
                 if data.references_error()
-                    || self.tcx.sess.has_errors()
+                    || self.tcx.sess.has_errors().is_some()
                     || self.is_tainted_by_errors()
                 {
                     // no need to overload user in such cases
@@ -1910,7 +1914,7 @@ fn maybe_report_ambiguity(
             }
 
             _ => {
-                if self.tcx.sess.has_errors() || self.is_tainted_by_errors() {
+                if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() {
                     return;
                 }
                 let mut err = struct_span_err!(
index 62c6c8454797a8f9592a5207a19b55e4b6761739..9ac8dc59a1d1ea9110f39f2fe8f4b6d2a8ec636e 100644 (file)
@@ -3,7 +3,6 @@
 use rustc_data_structures::obligation_forest::ProcessResult;
 use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
-use rustc_errors::ErrorGuaranteed;
 use rustc_infer::traits::ProjectionCacheKey;
 use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
 use rustc_middle::mir::interpret::ErrorHandled;
@@ -630,14 +629,12 @@ fn process_changed_obligations(
                                 ),
                             }
                         }
-                        (Err(ErrorHandled::Reported(ErrorGuaranteed)), _)
-                        | (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => {
-                            ProcessResult::Error(CodeSelectionError(
-                                SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(
-                                    ErrorGuaranteed,
-                                )),
-                            ))
-                        }
+                        (Err(ErrorHandled::Reported(reported)), _)
+                        | (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
+                            CodeSelectionError(SelectionError::NotConstEvaluatable(
+                                NotConstEvaluatable::Error(reported),
+                            )),
+                        ),
                         (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
                             span_bug!(
                                 obligation.cause.span(self.selcx.tcx()),
index bf94c61e6c2cef3b48fa06d3063a691da969ac01..a1efeb0b06b9b7fb5e4b680529399ec9f92ff3fc 100644 (file)
@@ -231,8 +231,8 @@ fn do_normalize_predicates<'tcx>(
             match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
                 Ok(predicates) => predicates,
                 Err(errors) => {
-                    infcx.report_fulfillment_errors(&errors, None, false);
-                    return Err(ErrorGuaranteed);
+                    let reported = infcx.report_fulfillment_errors(&errors, None, false);
+                    return Err(reported);
                 }
             };
 
@@ -258,13 +258,15 @@ fn do_normalize_predicates<'tcx>(
                 // represents a legitimate failure due to some kind of
                 // unconstrained variable, and it seems better not to ICE,
                 // all things considered.
-                tcx.sess.span_err(span, &fixup_err.to_string());
-                return Err(ErrorGuaranteed);
+                let reported = tcx.sess.span_err(span, &fixup_err.to_string());
+                return Err(reported);
             }
         };
         if predicates.needs_infer() {
-            tcx.sess.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
-            Err(ErrorGuaranteed)
+            let reported = tcx
+                .sess
+                .delay_span_bug(span, "encountered inference variables after `fully_resolve`");
+            Err(reported)
         } else {
             Ok(predicates)
         }
index 2f697c1fa27b79e3eb4f7d2a902a9a24f520fb5f..38be28c07ff1837045528590c2bbdc3a8b43308f 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_parse_format::{ParseMode, Parser, Piece, Position};
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 
 #[derive(Clone, Debug)]
 pub struct OnUnimplementedFormatString(Symbol);
@@ -47,8 +47,7 @@ fn parse_error(
     if let Some(note) = note {
         diag.note(note);
     }
-    diag.emit();
-    ErrorGuaranteed
+    diag.emit()
 }
 
 impl<'tcx> OnUnimplementedDirective {
@@ -59,7 +58,7 @@ fn parse(
         span: Span,
         is_root: bool,
     ) -> Result<Self, ErrorGuaranteed> {
-        let mut errored = false;
+        let mut errored = None;
         let mut item_iter = items.iter();
 
         let parse_value = |value_str| {
@@ -91,8 +90,8 @@ fn parse(
                     )
                 })?;
             attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
-                if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
-                    errored = true;
+                if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
+                    errored = Some(guar);
                 }
                 true
             });
@@ -134,13 +133,10 @@ fn parse(
                 && note.is_none()
             {
                 if let Some(items) = item.meta_item_list() {
-                    if let Ok(subcommand) =
-                        Self::parse(tcx, item_def_id, &items, item.span(), false)
-                    {
-                        subcommands.push(subcommand);
-                    } else {
-                        errored = true;
-                    }
+                    match Self::parse(tcx, item_def_id, &items, item.span(), false) {
+                        Ok(subcommand) => subcommands.push(subcommand),
+                        Err(reported) => errored = Some(reported),
+                    };
                     continue;
                 }
             } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
@@ -163,8 +159,8 @@ fn parse(
             );
         }
 
-        if errored {
-            Err(ErrorGuaranteed)
+        if let Some(reported) = errored {
+            Err(reported)
         } else {
             Ok(OnUnimplementedDirective {
                 condition,
@@ -203,7 +199,9 @@ pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, Er
                 append_const_msg: None,
             }))
         } else {
-            return Err(ErrorGuaranteed);
+            let reported =
+                tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str");
+            return Err(reported);
         };
         debug!("of_item({:?}) = {:?}", item_def_id, result);
         result
@@ -327,7 +325,7 @@ fn verify(
                         match generics.params.iter().find(|param| param.name == s) {
                             Some(_) => (),
                             None => {
-                                struct_span_err!(
+                                let reported = struct_span_err!(
                                     tcx.sess,
                                     span,
                                     E0230,
@@ -340,20 +338,20 @@ fn verify(
                                     }
                                 )
                                 .emit();
-                                result = Err(ErrorGuaranteed);
+                                result = Err(reported);
                             }
                         }
                     }
                     // `{:1}` and `{}` are not to be used
                     Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
-                        struct_span_err!(
+                        let reported = struct_span_err!(
                             tcx.sess,
                             span,
                             E0231,
                             "only named substitution parameters are allowed"
                         )
                         .emit();
-                        result = Err(ErrorGuaranteed);
+                        result = Err(reported);
                     }
                 },
             }
index 11f0507d6fd61175d8c0125bad91df0de2cdd855..614a5e048099762c8d592711b3ac66875d6a876a 100644 (file)
@@ -1396,7 +1396,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
                 let node_item =
                     assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
-                        .map_err(|ErrorGuaranteed| ())?;
+                        .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
                     // Non-specializable items are always projectable.
index 8af4606db85200eec7d87ecd70e71776ee725ffe..cf929ee3cc056729ba946ec8266c7f6017094a36 100644 (file)
@@ -29,7 +29,7 @@
 use crate::traits::ProjectionCacheKey;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_errors::{Diagnostic, ErrorGuaranteed};
+use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::LateBoundRegionConversionTime;
@@ -674,8 +674,8 @@ fn evaluate_predicate_recursively<'o>(
                                 Err(_) => Ok(EvaluatedToErr),
                             }
                         }
-                        (Err(ErrorHandled::Reported(ErrorGuaranteed)), _)
-                        | (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => Ok(EvaluatedToErr),
+                        (Err(ErrorHandled::Reported(_)), _)
+                        | (_, Err(ErrorHandled::Reported(_))) => Ok(EvaluatedToErr),
                         (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
                             span_bug!(
                                 obligation.cause.span(self.tcx()),
index a8a53c297d1a47ae89610beeedbd16b0fd5adc0c..79471065ccc67899834f1b07533a865aca6c5610 100644 (file)
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, EmissionGuarantee};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 
 use super::util::impl_trait_ref_and_oblig;
 use super::{FulfillmentContext, SelectionContext};
@@ -377,8 +377,7 @@ fn report_negative_positive_conflict(
         }
     }
 
-    sg.has_errored = true;
-    err.emit();
+    sg.has_errored = Some(err.emit());
 }
 
 fn report_conflicting_impls(
@@ -394,7 +393,13 @@ fn report_conflicting_impls(
     // Work to be done after we've built the DiagnosticBuilder. We have to define it
     // now because the struct_lint methods don't return back the DiagnosticBuilder
     // that's passed in.
-    let decorate = |err: LintDiagnosticBuilder<'_>| {
+    fn decorate<G: EmissionGuarantee>(
+        tcx: TyCtxt<'_>,
+        overlap: OverlapError,
+        used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
+        impl_span: Span,
+        err: LintDiagnosticBuilder<'_, G>,
+    ) -> G {
         let msg = format!(
             "conflicting implementations of trait `{}`{}{}",
             overlap.trait_desc,
@@ -440,17 +445,25 @@ fn report_conflicting_impls(
             coherence::add_placeholder_note(&mut err);
         }
         err.emit()
-    };
+    }
 
     match used_to_be_allowed {
         None => {
-            sg.has_errored = true;
-            if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) {
+            let reported = if overlap.with_impl.is_local()
+                || !tcx.orphan_check_crate(()).contains(&impl_def_id)
+            {
                 let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
-                decorate(LintDiagnosticBuilder::new(err.forget_guarantee()));
+                Some(decorate(
+                    tcx,
+                    overlap,
+                    used_to_be_allowed,
+                    impl_span,
+                    LintDiagnosticBuilder::new(err),
+                ))
             } else {
-                tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check");
-            }
+                Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
+            };
+            sg.has_errored = reported;
         }
         Some(kind) => {
             let lint = match kind {
@@ -461,8 +474,10 @@ fn report_conflicting_impls(
                 lint,
                 tcx.hir().local_def_id_to_hir_id(impl_def_id),
                 impl_span,
-                decorate,
-            )
+                |ldb| {
+                    decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb);
+                },
+            );
         }
     };
 }
index 41467ce2f622f07ef50a4e01aa76ec3680384920..295a91959eb194f0bdb9cad22b0621c160d35fa8 100644 (file)
@@ -306,9 +306,9 @@ fn resolve_associated_item<'tcx>(
                         resolved_ty,
                     );
                     let span = tcx.def_span(leaf_def.item.def_id);
-                    tcx.sess.delay_span_bug(span, &msg);
+                    let reported = tcx.sess.delay_span_bug(span, &msg);
 
-                    return Err(ErrorGuaranteed);
+                    return Err(reported);
                 }
             }
 
index 7e9abe3a250db2c03deff124ab88fd7835b051fb..5f01559226c77779279c03ceeb1db51645b2c08d 100644 (file)
@@ -1,6 +1,6 @@
 use crate::astconv::AstConv;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{pluralize, struct_span_err, Applicability};
+use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty;
@@ -195,7 +195,8 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
         ty_param_name: &str,
         assoc_name: Ident,
         span: Span,
-    ) where
+    ) -> ErrorGuaranteed
+    where
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
     {
         // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
@@ -231,7 +232,7 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
             err.span_label(span, format!("associated type `{}` not found", assoc_name));
         }
 
-        err.emit();
+        err.emit()
     }
 
     /// When there are any missing associated types, emit an E0191 error and attempt to supply a
index e8b64587eeea6a799665b9128e1747189a66ff08..d56c521d23d32058d3f40e3728063b9abd67fc08 100644 (file)
@@ -6,7 +6,7 @@
 use crate::errors::AssocTypeBindingNotAllowed;
 use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
+use rustc_errors::{struct_span_err, Applicability, Diagnostic};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -456,51 +456,55 @@ pub(crate) fn check_generic_arg_count(
 
         let mut invalid_args = vec![];
 
-        let mut check_lifetime_args = |min_expected_args: usize,
-                                       max_expected_args: usize,
-                                       provided_args: usize,
-                                       late_bounds_ignore: bool|
-         -> bool {
-            if (min_expected_args..=max_expected_args).contains(&provided_args) {
-                return true;
-            }
+        let mut check_lifetime_args =
+            |min_expected_args: usize,
+             max_expected_args: usize,
+             provided_args: usize,
+             late_bounds_ignore: bool| {
+                if (min_expected_args..=max_expected_args).contains(&provided_args) {
+                    return Ok(());
+                }
 
-            if late_bounds_ignore {
-                return true;
-            }
+                if late_bounds_ignore {
+                    return Ok(());
+                }
 
-            if provided_args > max_expected_args {
-                invalid_args.extend(
-                    gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()),
-                );
-            };
+                if provided_args > max_expected_args {
+                    invalid_args.extend(
+                        gen_args.args[max_expected_args..provided_args]
+                            .iter()
+                            .map(|arg| arg.span()),
+                    );
+                };
 
-            let gen_args_info = if provided_args > min_expected_args {
-                invalid_args.extend(
-                    gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()),
-                );
-                let num_redundant_args = provided_args - min_expected_args;
-                GenericArgsInfo::ExcessLifetimes { num_redundant_args }
-            } else {
-                let num_missing_args = min_expected_args - provided_args;
-                GenericArgsInfo::MissingLifetimes { num_missing_args }
+                let gen_args_info = if provided_args > min_expected_args {
+                    invalid_args.extend(
+                        gen_args.args[min_expected_args..provided_args]
+                            .iter()
+                            .map(|arg| arg.span()),
+                    );
+                    let num_redundant_args = provided_args - min_expected_args;
+                    GenericArgsInfo::ExcessLifetimes { num_redundant_args }
+                } else {
+                    let num_missing_args = min_expected_args - provided_args;
+                    GenericArgsInfo::MissingLifetimes { num_missing_args }
+                };
+
+                let reported = WrongNumberOfGenericArgs::new(
+                    tcx,
+                    gen_args_info,
+                    seg,
+                    gen_params,
+                    has_self as usize,
+                    gen_args,
+                    def_id,
+                )
+                .diagnostic()
+                .emit();
+
+                Err(reported)
             };
 
-            WrongNumberOfGenericArgs::new(
-                tcx,
-                gen_args_info,
-                seg,
-                gen_params,
-                has_self as usize,
-                gen_args,
-                def_id,
-            )
-            .diagnostic()
-            .emit();
-
-            false
-        };
-
         let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
         let max_expected_lifetime_args = param_counts.lifetimes;
         let num_provided_lifetime_args = gen_args.num_lifetime_params();
@@ -527,7 +531,7 @@ pub(crate) fn check_generic_arg_count(
                 "check_types_and_consts"
             );
             if (expected_min..=expected_max).contains(&provided) {
-                return true;
+                return Ok(());
             }
 
             let num_default_params = expected_max - expected_min;
@@ -561,7 +565,7 @@ pub(crate) fn check_generic_arg_count(
 
             debug!(?gen_args_info);
 
-            WrongNumberOfGenericArgs::new(
+            let reported = WrongNumberOfGenericArgs::new(
                 tcx,
                 gen_args_info,
                 seg,
@@ -573,7 +577,7 @@ pub(crate) fn check_generic_arg_count(
             .diagnostic()
             .emit_unless(gen_args.has_err());
 
-            false
+            Err(reported)
         };
 
         let args_correct = {
@@ -599,11 +603,9 @@ pub(crate) fn check_generic_arg_count(
 
         GenericArgCountResult {
             explicit_late_bound,
-            correct: if lifetimes_correct && args_correct {
-                Ok(())
-            } else {
-                Err(GenericArgCountMismatch { reported: Some(ErrorGuaranteed), invalid_args })
-            },
+            correct: lifetimes_correct.and(args_correct).map_err(|reported| {
+                GenericArgCountMismatch { reported: Some(reported), invalid_args }
+            }),
         }
     }
 
@@ -700,7 +702,9 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
                     LATE_BOUND_LIFETIME_ARGUMENTS,
                     args.args[0].id(),
                     multispan,
-                    |lint| lint.build(msg).emit(),
+                    |lint| {
+                        lint.build(msg).emit();
+                    },
                 );
             }
 
index 144953caa4c3be3a4e5e7438bf3178632947cc82..b04d304d2ca15f930c43097b4300058531c794b3 100644 (file)
@@ -1570,7 +1570,7 @@ fn report_ambiguous_associated_type(
         type_str: &str,
         trait_str: &str,
         name: Symbol,
-    ) {
+    ) -> ErrorGuaranteed {
         let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
         if let (true, Ok(snippet)) = (
             self.tcx()
@@ -1594,7 +1594,7 @@ fn report_ambiguous_associated_type(
                 Applicability::HasPlaceholders,
             );
         }
-        err.emit();
+        err.emit()
     }
 
     // Search for a bound on a type parameter which includes the associated item
@@ -1661,13 +1661,13 @@ fn one_bound_for_assoc_type<I>(
             (Some(bound), _) => (bound, matching_candidates.next()),
             (None, Some(bound)) => (bound, const_candidates.next()),
             (None, None) => {
-                self.complain_about_assoc_type_not_found(
+                let reported = self.complain_about_assoc_type_not_found(
                     all_candidates,
                     &ty_param_name(),
                     assoc_name,
                     span,
                 );
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
         };
         debug!("one_bound_for_assoc_type: bound = {:?}", bound);
@@ -1752,9 +1752,9 @@ fn one_bound_for_assoc_type<I>(
                     where_bounds.join(",\n"),
                 ));
             }
-            err.emit();
+            let reported = err.emit();
             if !where_bounds.is_empty() {
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
         }
 
@@ -1811,7 +1811,8 @@ pub fn associated_path_to_ty(
                 // trait reference.
                 let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
                     // A cycle error occurred, most likely.
-                    return Err(ErrorGuaranteed);
+                    let guar = tcx.sess.delay_span_bug(span, "expected cycle error");
+                    return Err(guar);
                 };
 
                 self.one_bound_for_assoc_type(
@@ -1828,10 +1829,10 @@ pub fn associated_path_to_ty(
                 | Res::Def(DefKind::TyParam, param_did),
             ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
             _ => {
-                if variant_resolution.is_some() {
+                let reported = if variant_resolution.is_some() {
                     // Variant in type position
                     let msg = format!("expected type, found variant `{}`", assoc_ident);
-                    tcx.sess.span_err(span, &msg);
+                    tcx.sess.span_err(span, &msg)
                 } else if qself_ty.is_enum() {
                     let mut err = struct_span_err!(
                         tcx.sess,
@@ -1870,17 +1871,19 @@ pub fn associated_path_to_ty(
                         err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
                     }
 
-                    err.emit();
-                } else if !qself_ty.references_error() {
+                    err.emit()
+                } else if let Some(reported) = qself_ty.error_reported() {
+                    reported
+                } else {
                     // Don't print `TyErr` to the user.
                     self.report_ambiguous_associated_type(
                         span,
                         &qself_ty.to_string(),
                         "Trait",
                         assoc_ident.name,
-                    );
-                }
-                return Err(ErrorGuaranteed);
+                    )
+                };
+                return Err(reported);
             }
         };
 
@@ -1898,8 +1901,8 @@ pub fn associated_path_to_ty(
         // but it was used in a type position.
         let Some(item) = item else {
             let msg = format!("found associated const `{assoc_ident}` when type was expected");
-            tcx.sess.struct_span_err(span, &msg).emit();
-            return Err(ErrorGuaranteed);
+            let guar = tcx.sess.struct_span_err(span, &msg).emit();
+            return Err(guar);
         };
 
         let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
@@ -2737,7 +2740,7 @@ fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
                                 sugg,
                                 Applicability::MachineApplicable,
                             )
-                            .emit()
+                            .emit();
                     },
                 );
             }
index d3e9820834ab9310ca54a214ae0a775a56cdf9af..7ce428ea12466d33e2f9efff4c0d89f7716fa4e2 100644 (file)
@@ -91,8 +91,8 @@ fn pointer_kind(
 
         let t = self.resolve_vars_if_possible(t);
 
-        if t.references_error() {
-            return Err(ErrorGuaranteed);
+        if let Some(reported) = t.error_reported() {
+            return Err(reported);
         }
 
         if self.type_is_known_to_be_sized_modulo_regions(t, span) {
@@ -139,10 +139,11 @@ fn pointer_kind(
             | ty::Adt(..)
             | ty::Never
             | ty::Error(_) => {
-                self.tcx
+                let reported = self
+                    .tcx
                     .sess
                     .delay_span_bug(span, &format!("`{:?}` should be sized but is not?", t));
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
         })
     }
@@ -174,7 +175,7 @@ pub enum CastError {
 }
 
 impl From<ErrorGuaranteed> for CastError {
-    fn from(ErrorGuaranteed: ErrorGuaranteed) -> Self {
+    fn from(_: ErrorGuaranteed) -> Self {
         CastError::ErrorGuaranteed
     }
 }
@@ -213,8 +214,8 @@ pub fn new(
         // inference is more completely known.
         match cast_ty.kind() {
             ty::Dynamic(..) | ty::Slice(..) => {
-                check.report_cast_to_unsized_type(fcx);
-                Err(ErrorGuaranteed)
+                let reported = check.report_cast_to_unsized_type(fcx);
+                Err(reported)
             }
             _ => Ok(check),
         }
@@ -588,9 +589,11 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
         }
     }
 
-    fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) {
-        if self.cast_ty.references_error() || self.expr_ty.references_error() {
-            return;
+    fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) -> ErrorGuaranteed {
+        if let Some(reported) =
+            self.cast_ty.error_reported().or_else(|| self.expr_ty.error_reported())
+        {
+            return reported;
         }
 
         let tstr = fcx.ty_to_string(self.cast_ty);
@@ -651,7 +654,7 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx>) {
                 err.span_help(self.expr.span, "consider using a box or reference as appropriate");
             }
         }
-        err.emit();
+        err.emit()
     }
 
     fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
index 9016a8ffe9add582bc205c654db926165762a35a..e57d55fdc2377394fe5d6f0804a8cf80595231d3 100644 (file)
@@ -49,7 +49,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
         }
         None => {
             tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
-                lint.build("use of calling convention not supported on this target").emit()
+                lint.build("use of calling convention not supported on this target").emit();
             });
         }
     }
@@ -136,7 +136,7 @@ pub(super) fn check_fn<'a, 'tcx>(
             };
 
             if let Some(header) = item {
-                tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
+                tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
             }
         };
 
@@ -625,11 +625,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
     origin: &hir::OpaqueTyOrigin,
 ) -> Result<(), ErrorGuaranteed> {
     if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
-        match origin {
+        let reported = match origin {
             hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
             _ => opaque_type_cycle_error(tcx, def_id, span),
-        }
-        Err(ErrorGuaranteed)
+        };
+        Err(reported)
     } else {
         Ok(())
     }
@@ -680,13 +680,15 @@ fn check_opaque_meets_bounds<'tcx>(
             trace!(?hidden_type);
             match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) {
                 Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
-                Err(ty_err) => tcx.sess.delay_span_bug(
-                    span,
-                    &format!(
-                        "could not check bounds on revealed type `{}`:\n{}",
-                        hidden_type, ty_err,
-                    ),
-                ),
+                Err(ty_err) => {
+                    tcx.sess.delay_span_bug(
+                        span,
+                        &format!(
+                            "could not check bounds on revealed type `{}`:\n{}",
+                            hidden_type, ty_err,
+                        ),
+                    );
+                }
             }
         }
 
@@ -1422,7 +1424,7 @@ pub(super) fn check_type_params_are_used<'tcx>(
     if ty.references_error() {
         // If there is already another error, do not emit
         // an error for not using a type parameter.
-        assert!(tcx.sess.has_errors());
+        assert!(tcx.sess.has_errors().is_some());
         return;
     }
 
@@ -1463,14 +1465,14 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 
 pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed;
 
-fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) {
+fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
     struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
         .span_label(span, "recursive `async fn`")
         .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
         .note(
             "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
         )
-        .emit();
+        .emit()
 }
 
 /// Emit an error for recursive opaque types.
@@ -1481,7 +1483,7 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) {
 ///
 /// If all the return expressions evaluate to `!`, then we explain that the error will go away
 /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
-fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
+fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> ErrorGuaranteed {
     let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
 
     let mut label = false;
@@ -1550,5 +1552,5 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
     if !label {
         err.span_label(span, "cannot resolve opaque type");
     }
-    err.emit();
+    err.emit()
 }
index d4a473adaf010e45059eabe57a343392d6663fff..f5477f7103cb3109525bb3b18623ebc8fbaec22b 100644 (file)
 
     let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span);
 
-    if let Err(ErrorGuaranteed) =
-        compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
-    {
+    if let Err(_) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) {
         return;
     }
 
-    if let Err(ErrorGuaranteed) =
-        compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
-    {
+    if let Err(_) = compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
         return;
     }
 
-    if let Err(ErrorGuaranteed) =
+    if let Err(_) =
         compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
     {
         return;
     }
 
-    if let Err(ErrorGuaranteed) = compare_synthetic_generics(tcx, impl_m, trait_m) {
+    if let Err(_) = compare_synthetic_generics(tcx, impl_m, trait_m) {
         return;
     }
 
-    if let Err(ErrorGuaranteed) =
-        compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
+    if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
     {
         return;
     }
 
-    if let Err(ErrorGuaranteed) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) {
+    if let Err(_) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) {
         return;
     }
 }
@@ -385,16 +380,16 @@ fn compare_predicate_entailment<'tcx>(
                 &terr,
                 false,
             );
-            diag.emit();
-            return Err(ErrorGuaranteed);
+
+            return Err(diag.emit());
         }
 
         // Check that all obligations are satisfied by the implementation's
         // version.
         let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
         if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-            return Err(ErrorGuaranteed);
+            let reported = infcx.report_fulfillment_errors(&errors, None, false);
+            return Err(reported);
         }
 
         // Finally, resolve all regions. This catches wily misuses of
@@ -450,13 +445,13 @@ fn check_region_bounds_on_impl_item<'tcx>(
                 .map_or(def_sp, |g| g.span)
         });
 
-        tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
+        let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
             span,
             item_kind,
             ident: impl_m.ident(tcx),
             generics_span,
         });
-        return Err(ErrorGuaranteed);
+        return Err(reported);
     }
 
     Ok(())
@@ -550,8 +545,8 @@ fn compare_self_type<'tcx>(
             } else {
                 err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
             }
-            err.emit();
-            return Err(ErrorGuaranteed);
+            let reported = err.emit();
+            return Err(reported);
         }
 
         (true, false) => {
@@ -570,8 +565,8 @@ fn compare_self_type<'tcx>(
             } else {
                 err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx));
             }
-            err.emit();
-            return Err(ErrorGuaranteed);
+            let reported = err.emit();
+            return Err(reported);
         }
     }
 
@@ -595,11 +590,9 @@ fn compare_number_of_generics<'tcx>(
 
     let item_kind = assoc_item_kind_str(impl_);
 
-    let mut err_occurred = false;
+    let mut err_occurred = None;
     for (kind, trait_count, impl_count) in matchings {
         if impl_count != trait_count {
-            err_occurred = true;
-
             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
                 let trait_item = tcx.hir().expect_trait_item(def_id);
                 if trait_item.generics.params.is_empty() {
@@ -690,11 +683,12 @@ fn compare_number_of_generics<'tcx>(
                 err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
             }
 
-            err.emit();
+            let reported = err.emit();
+            err_occurred = Some(reported);
         }
     }
 
-    if err_occurred { Err(ErrorGuaranteed) } else { Ok(()) }
+    if let Some(reported) = err_occurred { Err(reported) } else { Ok(()) }
 }
 
 fn compare_number_of_method_arguments<'tcx>(
@@ -772,8 +766,8 @@ fn compare_number_of_method_arguments<'tcx>(
                 impl_number_args
             ),
         );
-        err.emit();
-        return Err(ErrorGuaranteed);
+        let reported = err.emit();
+        return Err(reported);
     }
 
     Ok(())
@@ -789,7 +783,7 @@ fn compare_synthetic_generics<'tcx>(
     //     2. Explanation as to what is going on
     // If we get here, we already have the same number of generics, so the zip will
     // be okay.
-    let mut error_found = false;
+    let mut error_found = None;
     let impl_m_generics = tcx.generics_of(impl_m.def_id);
     let trait_m_generics = tcx.generics_of(trait_m.def_id);
     let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
@@ -918,11 +912,11 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
                 }
                 _ => unreachable!(),
             }
-            err.emit();
-            error_found = true;
+            let reported = err.emit();
+            error_found = Some(reported);
         }
     }
-    if error_found { Err(ErrorGuaranteed) } else { Ok(()) }
+    if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
 }
 
 fn compare_const_param_types<'tcx>(
@@ -979,8 +973,8 @@ fn compare_const_param_types<'tcx>(
                     trait_ty
                 ),
             );
-            err.emit();
-            return Err(ErrorGuaranteed);
+            let reported = err.emit();
+            return Err(reported);
         }
     }
 
@@ -1203,8 +1197,8 @@ fn compare_type_predicate_entailment<'tcx>(
         // version.
         let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
         if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-            return Err(ErrorGuaranteed);
+            let reported = infcx.report_fulfillment_errors(&errors, None, false);
+            return Err(reported);
         }
 
         // Finally, resolve all regions. This catches wily misuses of
@@ -1427,8 +1421,8 @@ pub fn check_type_bounds<'tcx>(
         // version.
         let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
         if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-            return Err(ErrorGuaranteed);
+            let reported = infcx.report_fulfillment_errors(&errors, None, false);
+            return Err(reported);
         }
 
         // Finally, resolve all regions. This catches wily misuses of
index 1849ece9f76d9aa1df6b11acfaf17fd5d2c1f8b7..d38777bea5990b4c1a5f4d805d035982dba5ec1b 100644 (file)
@@ -55,11 +55,11 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
             // already checked by coherence, but compilation may
             // not have been terminated.
             let span = tcx.def_span(drop_impl_did);
-            tcx.sess.delay_span_bug(
+            let reported = tcx.sess.delay_span_bug(
                 span,
                 &format!("should have been rejected by coherence check: {}", dtor_self_type),
             );
-            Err(ErrorGuaranteed)
+            Err(reported)
         }
     }
 }
@@ -94,7 +94,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             Err(_) => {
                 let item_span = tcx.def_span(self_type_did);
                 let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
-                struct_span_err!(
+                let reported = struct_span_err!(
                     tcx.sess,
                     drop_impl_span,
                     E0366,
@@ -109,15 +109,15 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
                     ),
                 )
                 .emit();
-                return Err(ErrorGuaranteed);
+                return Err(reported);
             }
         }
 
         let errors = fulfillment_cx.select_all_or_error(&infcx);
         if !errors.is_empty() {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(&errors, None, false);
-            return Err(ErrorGuaranteed);
+            let reported = infcx.report_fulfillment_errors(&errors, None, false);
+            return Err(reported);
         }
 
         // NB. It seems a bit... suspicious to use an empty param-env
@@ -258,7 +258,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) {
             let item_span = tcx.def_span(self_type_did);
             let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id());
-            struct_span_err!(
+            let reported = struct_span_err!(
                 tcx.sess,
                 predicate_sp,
                 E0367,
@@ -268,7 +268,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
             )
             .span_note(item_span, "the implementor must specify the same requirement")
             .emit();
-            result = Err(ErrorGuaranteed);
+            result = Err(reported);
         }
     }
 
index d944bb76241773dcc11e7b511f702fa8b2cc252f..0a720f1502503159b8c35010747fb7f88f96ce9a 100644 (file)
@@ -667,7 +667,7 @@ fn check_expr_break(
                 // else an error would have been flagged by the
                 // `loops` pass for using break with an expression
                 // where you are not supposed to.
-                assert!(expr_opt.is_none() || self.tcx.sess.has_errors());
+                assert!(expr_opt.is_none() || self.tcx.sess.has_errors().is_some());
             }
 
             // If we encountered a `break`, then (no surprise) it may be possible to break from the
@@ -1187,7 +1187,7 @@ fn check_expr_cast(
                     deferred_cast_checks.push(cast_check);
                     t_cast
                 }
-                Err(ErrorGuaranteed) => self.tcx.ty_error(),
+                Err(_) => self.tcx.ty_error(),
             }
         }
     }
index ed70b85e3f1478ad14a8c0c2366bcc55636d7661..e3439a6f1d963a7b2065e7073d57e334dd415b5b 100644 (file)
@@ -315,16 +315,18 @@ pub fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec<Adjustment<'tcx>>
                     }
                     // FIXME: currently we never try to compose autoderefs
                     // and ReifyFnPointer/UnsafeFnPointer, but we could.
-                    _ => self.tcx.sess.delay_span_bug(
-                        expr.span,
-                        &format!(
-                            "while adjusting {:?}, can't compose {:?} and {:?}",
-                            expr,
-                            entry.get(),
-                            adj
-                        ),
-                    ),
-                };
+                    _ => {
+                        self.tcx.sess.delay_span_bug(
+                            expr.span,
+                            &format!(
+                                "while adjusting {:?}, can't compose {:?} and {:?}",
+                                expr,
+                                entry.get(),
+                                adj
+                            ),
+                        );
+                    }
+                }
                 *entry.get_mut() = adj;
             }
         }
@@ -903,7 +905,7 @@ pub fn resolve_ty_and_res_fully_qualified_call(
             .or_else(|error| {
                 let result = match error {
                     method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
-                    _ => Err(ErrorGuaranteed),
+                    _ => Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()),
                 };
 
                 // If we have a path like `MyTrait::missing_method`, then don't register
index e79085fdad28dda5ae5fd594631a716e31bea2b6..4e1645adca5d3f258fda9267a304c500499885a3 100644 (file)
@@ -412,7 +412,9 @@ fn probe_op<OP, R>(
                         lint::builtin::TYVAR_BEHIND_RAW_POINTER,
                         scope_expr_id,
                         span,
-                        |lint| lint.build("type annotations needed").emit(),
+                        |lint| {
+                            lint.build("type annotations needed").emit();
+                        },
                     );
                 }
             } else {
index 62f7c382bc90c4629fa08c6b32029ecaa334a65b..16ffabb76a515f82947dcaf80b5ec9dca9012185 100644 (file)
@@ -81,7 +81,8 @@ pub fn resolve_type_vars_in_body(
 
         if self.is_tainted_by_errors() {
             // FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted.
-            wbcx.typeck_results.tainted_by_errors = Some(ErrorGuaranteed);
+            wbcx.typeck_results.tainted_by_errors =
+                Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
         }
 
         debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
@@ -662,7 +663,8 @@ fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
         // users of the typeck results don't produce extra errors, or worse, ICEs.
         if resolver.replaced_with_error {
             // FIXME(eddyb) keep track of `ErrorGuaranteed` from where the error was emitted.
-            self.typeck_results.tainted_by_errors = Some(ErrorGuaranteed);
+            self.typeck_results.tainted_by_errors =
+                Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
         }
 
         x
@@ -707,7 +709,7 @@ fn new(
     }
 
     fn report_type_error(&self, t: Ty<'tcx>) {
-        if !self.tcx.sess.has_errors() {
+        if !self.tcx.sess.has_errors().is_some() {
             self.infcx
                 .emit_inference_failure_err(
                     Some(self.body.id()),
@@ -721,7 +723,7 @@ fn report_type_error(&self, t: Ty<'tcx>) {
     }
 
     fn report_const_error(&self, c: ty::Const<'tcx>) {
-        if !self.tcx.sess.has_errors() {
+        if self.tcx.sess.has_errors().is_none() {
             self.infcx
                 .emit_inference_failure_err(
                     Some(self.body.id()),
index 5dfd444133a37ffb8b17d857be35936e23fe914b..4b23cc4db85ba9fa215889d946586ccb38cfc562 100644 (file)
@@ -21,7 +21,7 @@ pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
         for &impl_of_trait in impls_of_trait {
             match orphan_check_impl(tcx, impl_of_trait) {
                 Ok(()) => {}
-                Err(ErrorGuaranteed) => errors.push(impl_of_trait),
+                Err(_) => errors.push(impl_of_trait),
             }
         }
 
@@ -135,17 +135,19 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
         };
 
         if let Some((msg, label)) = msg {
-            struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
-            return Err(ErrorGuaranteed);
+            let reported =
+                struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
+            return Err(reported);
         }
     }
 
     if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
-        tcx.sess
+        let reported = tcx
+            .sess
             .struct_span_err(sp, "cannot implement trait on type alias impl trait")
             .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
             .emit();
-        return Err(ErrorGuaranteed);
+        return Err(reported);
     }
 
     Ok(())
index 3247a292242a34a3740628e533970507d04e5940..d422f355ad3a49a377014b6b2cf8b1ab6d5fbe4b 100644 (file)
@@ -1,4 +1,4 @@
-use rustc_errors::{Applicability, ErrorGuaranteed, StashKey};
+use rustc_errors::{Applicability, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -366,7 +366,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                                     owner, def_id,
                                 ),
                             );
-                            if let Some(ErrorGuaranteed) =
+                            if let Some(_) =
                                 tcx.typeck(owner).tainted_by_errors
                             {
                                 // Some error in the
index be4958ea062763424156f4f8a24ee52417fad10b..cb59438e3432f3ec3a72ac8b2acde464a6dac88a 100644 (file)
@@ -523,7 +523,7 @@ fn walk_struct_expr<'hir>(
                 // struct; however, when EUV is run during typeck, it
                 // may not. This will generate an error earlier in typeck,
                 // so we can just ignore it.
-                if !self.tcx().sess.has_errors() {
+                if !self.tcx().sess.has_errors().is_some() {
                     span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
                 }
             }
index d665b6d068e0676eaf291a4485ec7faac2b22366..5d4dfd3caefcc3b5fabcb168160d7bfc4ec4e434 100644 (file)
@@ -537,7 +537,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
-    if tcx.sess.err_count() == 0 { Ok(()) } else { Err(ErrorGuaranteed) }
+    if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
 }
 
 /// A quasi-deprecated helper used in rustdoc and clippy to get
index c0e7cd0b1f58016e0968015174f04ac22992a92c..42b7eec5d3aa9994488fc794999b4f09d18c0a70 100644 (file)
@@ -834,7 +834,9 @@ fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
                         {
                             match Cfg::parse(cfg_mi) {
                                 Ok(new_cfg) => cfg &= new_cfg,
-                                Err(e) => sess.span_err(e.span, e.msg),
+                                Err(e) => {
+                                    sess.span_err(e.span, e.msg);
+                                }
                             }
                         }
                     }
index 2b82575f71083626af0af14977bd5418b0957761..bd64e2b03ce0c8dc606ea9b41a664b5dda9e4634 100644 (file)
@@ -452,7 +452,7 @@ fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
         }
     }
 
-    if tcx.sess.diagnostic().has_errors_or_lint_errors() {
+    if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
         rustc_errors::FatalError.raise();
     }
 
index 728b7720f739d002878cb939d9d201e673517009..8db5f8b0cff8b01491f91da6a2e972dc468e2acc 100644 (file)
 
                     collector
                 });
-                if compiler.session().diagnostic().has_errors_or_lint_errors() {
+                if compiler.session().diagnostic().has_errors_or_lint_errors().is_some() {
                     FatalError.raise();
                 }
 
index f378915172a699ed1e14c659d58b6f6cb9356f97..f59222b780d3e22c224e06a2be78cd5d33ead9e1 100644 (file)
@@ -179,7 +179,7 @@ pub fn main() {
 
     let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() {
         Some(args) => main_args(&args),
-        _ => Err(ErrorGuaranteed),
+        _ => Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()),
     });
     process::exit(exit_code);
 }
@@ -692,7 +692,13 @@ fn main_args(at_args: &[String]) -> MainResult {
     // codes from `from_matches` here.
     let options = match config::Options::from_matches(&matches) {
         Ok(opts) => opts,
-        Err(code) => return if code == 0 { Ok(()) } else { Err(ErrorGuaranteed) },
+        Err(code) => {
+            return if code == 0 {
+                Ok(())
+            } else {
+                Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+            };
+        }
     };
     rustc_interface::util::run_in_thread_pool_with_globals(
         options.edition,
@@ -705,8 +711,8 @@ fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainRes
     match res {
         Ok(()) => Ok(()),
         Err(err) => {
-            diag.struct_err(&err).emit();
-            Err(ErrorGuaranteed)
+            let reported = diag.struct_err(&err).emit();
+            Err(reported)
         }
     }
 }
@@ -790,7 +796,7 @@ fn main_options(options: config::Options) -> MainResult {
                 (resolver.clone(), resolver_caches)
             };
 
-            if sess.diagnostic().has_errors_or_lint_errors() {
+            if sess.diagnostic().has_errors_or_lint_errors().is_some() {
                 sess.fatal("Compilation failed, aborting rustdoc");
             }
 
index 71fa71750f43a3240e025cccdaf11e75b7bfc6f7..81f371840ae4638ecc6534728216ae57dbf2a35c 100644 (file)
@@ -80,7 +80,7 @@ fn visit_item(&mut self, item: &Item) {
                             format!("<{}>", url),
                             Applicability::MachineApplicable,
                         )
-                        .emit()
+                        .emit();
                 });
             };
 
index c4aa31ad912305ec3b9968a58a17a1b94f47b494..8d9b3377a698691a9df7c0a58708cb371cda2b53 100644 (file)
@@ -91,7 +91,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
 
         // lambda that will use the lint to start a new diagnostic and add
         // a suggestion to it when needed.
-        let diag_builder = |lint: LintDiagnosticBuilder<'_>| {
+        let diag_builder = |lint: LintDiagnosticBuilder<'_, ()>| {
             let explanation = if is_ignore {
                 "`ignore` code blocks require valid Rust code for syntax highlighting; \
                     mark blocks that do not contain Rust code as text"
index f1bb766f467afdd65a4852b1ef2955f4c6d8bdff..2b17e3457d293eb93e1bd87ca75525a9d9fb7538 100644 (file)
@@ -125,7 +125,9 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
                 crate::lint::MISSING_DOC_CODE_EXAMPLES,
                 hir_id,
                 sp,
-                |lint| lint.build("missing code example in this documentation").emit(),
+                |lint| {
+                    lint.build("missing code example in this documentation").emit();
+                },
             );
         }
     } else if tests.found_tests > 0
@@ -135,7 +137,9 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
             crate::lint::PRIVATE_DOC_TESTS,
             hir_id,
             item.attr_span(cx.tcx),
-            |lint| lint.build("documentation test in private item").emit(),
+            |lint| {
+                lint.build("documentation test in private item").emit();
+            },
         );
     }
 }
index ee668501ae78b859dbe461d7e5e483b9c8dd3759..802b867a301aa5611bcdba471fbad793da7299b3 100644 (file)
@@ -50,7 +50,7 @@ fn check_fn(
         let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
         if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) {
             cx.lint(MISSING_ALLOWED_ATTR, |lint| {
-                lint.build("Missing 'allowed_attr' attribute").set_span(span).emit()
+                lint.build("Missing 'allowed_attr' attribute").set_span(span).emit();
             });
         }
     }
index e726f8402ef9d0edc8b39d59587efbd5e7b59dfb..bc153faa8925a73d952df3740a1a5a5bf63d1d9a 100644 (file)
@@ -34,7 +34,7 @@ fn check_crate(&mut self, cx: &LateContext) {
                     if !cx.sess().contains_name(attrs, $attr) {
                         cx.lint(CRATE_NOT_OKAY, |lint| {
                              let msg = format!("crate is not marked with #![{}]", $attr);
-                             lint.build(&msg).set_span(span).emit()
+                             lint.build(&msg).set_span(span).emit();
                         });
                     }
                 )*
index 4bbed5029802dbe9e43ea35cb3fd0faf148e0361..29d0abfbe53889e19ff961526ea02e8b6ed20c93 100644 (file)
@@ -30,7 +30,7 @@ fn check_crate(&mut self, cx: &LateContext) {
         let span = cx.tcx.def_span(CRATE_DEF_ID);
         if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) {
             cx.lint(CRATE_NOT_OKAY, |lint| {
-                lint.build("crate is not marked with #![crate_okay]").set_span(span).emit()
+                lint.build("crate is not marked with #![crate_okay]").set_span(span).emit();
             });
         }
     }
index 98ba8b12256562733b41e8d2bab6a63adc9da338..691cfb97d921858e5bec59e96f900620de8fbd08 100644 (file)
@@ -23,10 +23,10 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
     fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) {
         match it.ident.as_str() {
             "lintme" => cx.lint(TEST_LINT, |lint| {
-                lint.build("item is named 'lintme'").set_span(it.span).emit()
+                lint.build("item is named 'lintme'").set_span(it.span).emit();
             }),
             "pleaselintme" => cx.lint(PLEASE_LINT, |lint| {
-                lint.build("item is named 'pleaselintme'").set_span(it.span).emit()
+                lint.build("item is named 'pleaselintme'").set_span(it.span).emit();
             }),
             _ => {}
         }
index 42368ec36a028d03103b816740fa031e990740bb..285754928c2191bc324ca1473bfac333e4a9cd9c 100644 (file)
@@ -22,7 +22,7 @@ impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
         if it.ident.name.as_str() == "lintme" {
             cx.lint(TEST_LINT, |lint| {
-                lint.build("item is named 'lintme'").set_span(it.span).emit()
+                lint.build("item is named 'lintme'").set_span(it.span).emit();
             });
         }
     }
index 81feddf571323341dd4c9d224f7d20a865eaa7b4..3d5dba42b5f03b45326e1a25979cb6f732b27234 100644 (file)
@@ -32,12 +32,12 @@ impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
         if it.ident.name.as_str() == "lintme" {
             cx.lint(TEST_LINT, |lint| {
-                lint.build("item is named 'lintme'").set_span(it.span).emit()
+                lint.build("item is named 'lintme'").set_span(it.span).emit();
             });
         }
         if it.ident.name.as_str() == "lintmetoo" {
             cx.lint(TEST_GROUP, |lint| {
-                lint.build("item is named 'lintmetoo'").set_span(it.span).emit()
+                lint.build("item is named 'lintmetoo'").set_span(it.span).emit();
             });
         }
     }
index 4c541de04be0894d4a53ef53890043105b345630..a8c2feec453c8a87ec742a5656c13087abcdb4d2 100644 (file)
@@ -16,7 +16,7 @@ macro_rules! parse_or {
         ($method:ident $(,)* $($arg:expr),* $(,)*) => {
             match parser.$method($($arg,)*) {
                 Ok(val) => {
-                    if parser.sess.span_diagnostic.has_errors() {
+                    if parser.sess.span_diagnostic.has_errors().is_some() {
                         parser.sess.span_diagnostic.reset_err_count();
                         return None;
                     } else {
index fd738908170f86ef5264737ae24ab466228c146e..3728f3a19b44fc40ceccb60342ed4f5d99aeee75 100644 (file)
@@ -28,7 +28,7 @@ macro_rules! parse_macro_arg {
             let mut cloned_parser = (*parser).clone();
             match $parser(&mut cloned_parser) {
                 Ok(x) => {
-                    if parser.sess.span_diagnostic.has_errors() {
+                    if parser.sess.span_diagnostic.has_errors().is_some() {
                         parser.sess.span_diagnostic.reset_err_count();
                     } else {
                         // Parsing succeeded.
index 40a6d708d8cccb25911c89b0cf85295481c698ad..a34ceed3fc91fe76ea306acdae1b07077d4991dc 100644 (file)
@@ -235,7 +235,7 @@ pub(super) fn can_reset_errors(&self) -> bool {
     }
 
     pub(super) fn has_errors(&self) -> bool {
-        self.parse_sess.span_diagnostic.has_errors()
+        self.parse_sess.span_diagnostic.has_errors().is_some()
     }
 
     pub(super) fn reset_errors(&self) {