about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2020-04-12 04:24:25 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2020-04-16 19:00:30 +0300
commitd7c4081b18fbf50f2d260ea893b659aec0b1d84a (patch)
tree76d84766b5e8784ad5baa65ad2c5e2e240ae8e9c
parente22d4795d849d2c6a229ccb666db922ae5b76410 (diff)
downloadrust-d7c4081b18fbf50f2d260ea893b659aec0b1d84a.tar.gz
rust-d7c4081b18fbf50f2d260ea893b659aec0b1d84a.zip
mir/interpret: only use `ErrorHandled::Reported` for `ErrorReported`.
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs7
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs4
-rw-r--r--src/librustc_middle/mir/interpret/error.rs57
-rw-r--r--src/librustc_middle/ty/context.rs6
-rw-r--r--src/librustc_middle/ty/mod.rs3
-rw-r--r--src/librustc_mir/borrow_check/mod.rs4
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs16
-rw-r--r--src/librustc_mir/interpret/eval_context.rs9
-rw-r--r--src/librustc_mir/interpret/intern.rs5
-rw-r--r--src/librustc_mir/interpret/memory.rs9
-rw-r--r--src/librustc_mir/interpret/operand.rs3
-rw-r--r--src/librustc_mir/monomorphize/collector.rs3
-rw-r--r--src/librustc_mir_build/build/mod.rs3
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs15
-rw-r--r--src/librustc_typeck/check/writeback.rs11
-rw-r--r--src/librustc_typeck/collect/type_of.rs6
16 files changed, 87 insertions, 74 deletions
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 69f11ed57ac..7d0e6998db4 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -6,6 +6,7 @@ use crate::glue;
 use crate::traits::*;
 use crate::MemFlags;
 
+use rustc_errors::ErrorReported;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
 use rustc_middle::ty::layout::TyAndLayout;
@@ -447,8 +448,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|err| {
                     match err {
                         // errored or at least linted
-                        ErrorHandled::Reported => {}
-                        ErrorHandled::TooGeneric => bug!("codgen encountered polymorphic constant"),
+                        ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {}
+                        ErrorHandled::TooGeneric => {
+                            bug!("codegen encountered polymorphic constant")
+                        }
                     }
                     // Allow RalfJ to sleep soundly knowing that even refactorings that remove
                     // the above error (or silence it under some conditions) will not cause UB.
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 4189570a0da..ebeb5df6327 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -304,8 +304,8 @@ pub fn unexpected_hidden_region_diagnostic(
         // down this path which gives a decent human readable
         // explanation.
         //
-        // (*) if not, the `tainted_by_errors` flag would be set to
-        // true in any case, so we wouldn't be here at all.
+        // (*) if not, the `tainted_by_errors` field would be set to
+        // `Some(ErrorReported)` in any case, so we wouldn't be here at all.
         note_and_explain_free_region(
             tcx,
             &mut err,
diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs
index 7844fb10840..91646b3ba54 100644
--- a/src/librustc_middle/mir/interpret/error.rs
+++ b/src/librustc_middle/mir/interpret/error.rs
@@ -8,7 +8,7 @@ use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
 use rustc_data_structures::sync::Lock;
-use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::definitions::DefPathData;
 use rustc_macros::HashStable;
@@ -19,25 +19,16 @@ use std::{any::Any, fmt, mem};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
-    /// Already reported a lint or an error for this evaluation.
-    Reported,
+    /// Already reported an error for this evaluation, and the compilation is
+    /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
+    Reported(ErrorReported),
+    /// Already emitted a lint for this evaluation.
+    Linted,
     /// Don't emit an error, the evaluation failed because the MIR was generic
     /// and the substs didn't fully monomorphize it.
     TooGeneric,
 }
 
-impl ErrorHandled {
-    pub fn assert_reported(self) {
-        match self {
-            ErrorHandled::Reported => {}
-            ErrorHandled::TooGeneric => bug!(
-                "MIR interpretation failed without reporting an error \
-                 even though it was fully monomorphized"
-            ),
-        }
-    }
-}
-
 CloneTypeFoldableImpls! {
     ErrorHandled,
 }
@@ -84,15 +75,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
         tcx: TyCtxtAt<'tcx>,
         message: &str,
         emit: impl FnOnce(DiagnosticBuilder<'_>),
-    ) -> Result<(), ErrorHandled> {
+    ) -> ErrorHandled {
         self.struct_generic(tcx, message, emit, None)
     }
 
     pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled {
-        match self.struct_error(tcx, message, |mut e| e.emit()) {
-            Ok(_) => ErrorHandled::Reported,
-            Err(x) => x,
-        }
+        self.struct_error(tcx, message, |mut e| e.emit())
     }
 
     pub fn report_as_lint(
@@ -102,7 +90,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
         lint_root: hir::HirId,
         span: Option<Span>,
     ) -> ErrorHandled {
-        match self.struct_generic(
+        self.struct_generic(
             tcx,
             message,
             |mut lint: DiagnosticBuilder<'_>| {
@@ -122,10 +110,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
                 lint.emit();
             },
             Some(lint_root),
-        ) {
-            Ok(_) => ErrorHandled::Reported,
-            Err(err) => err,
-        }
+        )
     }
 
     /// Create a diagnostic for this const eval error.
@@ -143,12 +128,14 @@ impl<'tcx> ConstEvalErr<'tcx> {
         message: &str,
         emit: impl FnOnce(DiagnosticBuilder<'_>),
         lint_root: Option<hir::HirId>,
-    ) -> Result<(), ErrorHandled> {
+    ) -> ErrorHandled {
         let must_error = match self.error {
             err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
-                return Err(ErrorHandled::TooGeneric);
+                return ErrorHandled::TooGeneric;
+            }
+            err_inval!(TypeckError(error_reported)) => {
+                return ErrorHandled::Reported(error_reported);
             }
-            err_inval!(TypeckError) => return Err(ErrorHandled::Reported),
             // We must *always* hard error on these, even if the caller wants just a lint.
             err_inval!(Layout(LayoutError::SizeOverflow(_))) => true,
             _ => false,
@@ -183,6 +170,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
             // caller thinks anyway.
             // See <https://github.com/rust-lang/rust/pull/63152>.
             finish(struct_error(tcx, &err_msg), None);
+            ErrorHandled::Reported(ErrorReported)
         } else {
             // Regular case.
             if let Some(lint_root) = lint_root {
@@ -200,12 +188,13 @@ impl<'tcx> ConstEvalErr<'tcx> {
                     tcx.span,
                     |lint| finish(lint.build(message), Some(err_msg)),
                 );
+                ErrorHandled::Linted
             } else {
                 // Report as hard error.
                 finish(struct_error(tcx, message), Some(err_msg));
+                ErrorHandled::Reported(ErrorReported)
             }
         }
-        Ok(())
     }
 }
 
@@ -246,7 +235,9 @@ fn print_backtrace(backtrace: &mut Backtrace) {
 impl From<ErrorHandled> for InterpErrorInfo<'_> {
     fn from(err: ErrorHandled) -> Self {
         match err {
-            ErrorHandled::Reported => err_inval!(ReferencedConstant),
+            ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {
+                err_inval!(ReferencedConstant)
+            }
             ErrorHandled::TooGeneric => err_inval!(TooGeneric),
         }
         .into()
@@ -288,7 +279,7 @@ pub enum InvalidProgramInfo<'tcx> {
     /// which already produced an error.
     ReferencedConstant,
     /// Abort in case type errors are reached.
-    TypeckError,
+    TypeckError(ErrorReported),
     /// An error occurred during layout computation.
     Layout(layout::LayoutError<'tcx>),
     /// An invalid transmute happened.
@@ -301,7 +292,9 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
         match self {
             TooGeneric => write!(f, "encountered overly generic constant"),
             ReferencedConstant => write!(f, "referenced constant has errors"),
-            TypeckError => write!(f, "encountered constants with type errors, stopping evaluation"),
+            TypeckError(ErrorReported) => {
+                write!(f, "encountered constants with type errors, stopping evaluation")
+            }
             Layout(ref err) => write!(f, "{}", err),
             TransmuteSizeDiff(from_ty, to_ty) => write!(
                 f,
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 0762c0eed99..3eec58251a0 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -410,8 +410,8 @@ pub struct TypeckTables<'tcx> {
     pub used_trait_imports: Lrc<DefIdSet>,
 
     /// If any errors occurred while type-checking this body,
-    /// this field will be set to `true`.
-    pub tainted_by_errors: bool,
+    /// this field will be set to `Some(ErrorReported)`.
+    pub tainted_by_errors: Option<ErrorReported>,
 
     /// All the opaque types that are restricted to concrete types
     /// by this function.
@@ -447,7 +447,7 @@ impl<'tcx> TypeckTables<'tcx> {
             fru_field_types: Default::default(),
             coercion_casts: Default::default(),
             used_trait_imports: Lrc::new(Default::default()),
-            tainted_by_errors: false,
+            tainted_by_errors: None,
             concrete_opaque_types: Default::default(),
             upvar_list: Default::default(),
             generator_interior_types: Default::default(),
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 25d900fbc87..9f095847099 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -27,6 +27,7 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sorted_map::SortedIndexMultiMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{self, par_iter, ParallelIterator};
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
@@ -2388,7 +2389,7 @@ impl<'tcx> AdtDef {
                     None
                 }
             }
-            Err(ErrorHandled::Reported) => {
+            Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {
                 if !expr_did.is_local() {
                     span_bug!(
                         tcx.def_span(expr_did),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 52847af214f..ff7cd9f25db 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -3,7 +3,7 @@
 use rustc_ast::ast::Name;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::{def_id::DefId, HirId, Node};
 use rustc_index::bit_set::BitSet;
@@ -135,7 +135,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     // Gather the upvars of a closure, if any.
     let tables = tcx.typeck_tables_of(def_id);
-    if tables.tainted_by_errors {
+    if let Some(ErrorReported) = tables.tainted_by_errors {
         infcx.set_tainted_by_errors();
     }
     let upvars: Vec<_> = tables
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 3f0774767fd..8cb0ea91bc2 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -213,13 +213,10 @@ fn validate_and_turn_into_const<'tcx>(
 
     val.map_err(|error| {
         let err = error_to_const_error(&ecx, error);
-        match err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
+        err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
             diag.note(note_on_undefined_behavior_error());
             diag.emit();
-        }) {
-            Ok(_) => ErrorHandled::Reported,
-            Err(err) => err,
-        }
+        })
     })
 }
 
@@ -292,11 +289,10 @@ pub fn const_eval_raw_provider<'tcx>(
     let cid = key.value;
     let def_id = cid.instance.def.def_id();
 
-    if def_id.is_local()
-        && tcx.has_typeck_tables(def_id)
-        && tcx.typeck_tables_of(def_id).tainted_by_errors
-    {
-        return Err(ErrorHandled::Reported);
+    if def_id.is_local() && tcx.has_typeck_tables(def_id) {
+        if let Some(error_reported) = tcx.typeck_tables_of(def_id).tainted_by_errors {
+            return Err(ErrorHandled::Reported(error_reported));
+        }
     }
 
     let is_static = tcx.is_static(def_id);
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index f111eecb945..fcbb2535797 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -400,11 +400,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, mir::ReadOnlyBodyAndCache<'tcx, 'tcx>> {
         // do not continue if typeck errors occurred (can only occur in local crate)
         let did = instance.def_id();
-        if did.is_local()
-            && self.tcx.has_typeck_tables(did)
-            && self.tcx.typeck_tables_of(did).tainted_by_errors
-        {
-            throw_inval!(TypeckError)
+        if did.is_local() && self.tcx.has_typeck_tables(did) {
+            if let Some(error_reported) = self.tcx.typeck_tables_of(did).tainted_by_errors {
+                throw_inval!(TypeckError(error_reported))
+            }
         }
         trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
         if let Some(promoted) = promoted {
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index af415b3837f..480415676f6 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -5,6 +5,7 @@
 
 use super::validity::RefTracking;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_middle::mir::interpret::{ErrorHandled, InterpResult};
 use rustc_middle::ty::{self, Ty};
@@ -337,7 +338,9 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
                         diag.emit();
                     },
                 ) {
-                    Ok(()) | Err(ErrorHandled::TooGeneric) | Err(ErrorHandled::Reported) => {}
+                    ErrorHandled::TooGeneric
+                    | ErrorHandled::Reported(ErrorReported)
+                    | ErrorHandled::Linted => {}
                 }
             }
         }
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index bcad7855c37..efc43afd0f0 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -18,8 +18,8 @@ use rustc_middle::ty::{self, query::TyCtxtAt, Instance, ParamEnv};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
-    AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, ErrorHandled, GlobalAlloc,
-    GlobalId, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar,
+    AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, GlobalAlloc, GlobalId,
+    InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar,
 };
 use crate::util::pretty;
 
@@ -462,10 +462,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                         // no need to report anything, the const_eval call takes care of that
                         // for statics
                         assert!(tcx.is_static(def_id));
-                        match err {
-                            ErrorHandled::Reported => err_inval!(ReferencedConstant),
-                            ErrorHandled::TooGeneric => err_inval!(TooGeneric),
-                        }
+                        err
                     })?;
                 // Make sure we use the ID of the resolved memory, not the lazy one!
                 let id = raw_const.alloc_id;
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 648c1f5347c..2317a1fea07 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -4,6 +4,7 @@
 use std::convert::TryFrom;
 use std::fmt::Write;
 
+use rustc_errors::ErrorReported;
 use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
 use rustc_middle::ty::layout::{IntegerExt, PrimitiveExt, TyAndLayout};
@@ -518,7 +519,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Early-return cases.
         let val_val = match val.val {
             ty::ConstKind::Param(_) => throw_inval!(TooGeneric),
-            ty::ConstKind::Error => throw_inval!(TypeckError),
+            ty::ConstKind::Error => throw_inval!(TypeckError(ErrorReported)),
             ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 let instance = self.resolve(def_id, substs)?;
                 // We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index d8ceda96a25..ff62f02a191 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -178,6 +178,7 @@ use crate::monomorphize;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -602,7 +603,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 match self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
                     Ok(val) => collect_const_value(self.tcx, val, self.output),
-                    Err(ErrorHandled::Reported) => {}
+                    Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
                     Err(ErrorHandled::TooGeneric) => span_bug!(
                         self.tcx.def_span(def_id),
                         "collection encountered polymorphic constant",
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index 04cb509d44e..6911c09c518 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -3,6 +3,7 @@ use crate::build::scope::DropKind;
 use crate::hair::cx::Cx;
 use crate::hair::{BindingMode, LintLevel, PatKind};
 use rustc_attr::{self as attr, UnwindAttr};
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items;
@@ -59,7 +60,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
 
     tcx.infer_ctxt().enter(|infcx| {
         let cx = Cx::new(&infcx, id);
-        let body = if cx.tables().tainted_by_errors {
+        let body = if let Some(ErrorReported) = cx.tables().tainted_by_errors {
             build::construct_error(cx, body_id)
         } else if cx.body_owner_kind.is_fn_or_closure() {
             // fetch the fully liberated fn signature (that is, all bound
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index fef7adf0224..8ef40ceae78 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -12,7 +12,7 @@ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCod
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate};
@@ -653,8 +653,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             }
 
             // Already reported in the query.
-            ConstEvalFailure(ErrorHandled::Reported) => {
-                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
+            ConstEvalFailure(ErrorHandled::Reported(ErrorReported)) => {
+                // FIXME(eddyb) remove this once `ErrorReported` becomes a proof token.
+                self.tcx.sess.delay_span_bug(span, "`ErrorReported` without an error");
+                return;
+            }
+
+            // Already reported in the query, but only as a lint.
+            // This shouldn't actually happen for constants used in types, modulo
+            // bugs. The `delay_span_bug` here ensures it won't be ignored.
+            ConstEvalFailure(ErrorHandled::Linted) => {
+                self.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
                 return;
             }
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 990cc84d029..f541b257e8f 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -5,6 +5,7 @@
 use crate::check::FnCtxt;
 
 use rustc_data_structures::sync::Lrc;
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefIdSet;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -75,7 +76,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.tables.upvar_list =
             mem::replace(&mut self.tables.borrow_mut().upvar_list, Default::default());
 
-        wbcx.tables.tainted_by_errors |= self.is_tainted_by_errors();
+        if self.is_tainted_by_errors() {
+            // FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
+            wbcx.tables.tainted_by_errors = Some(ErrorReported);
+        }
 
         debug!("writeback: tables for {:?} are {:#?}", item_def_id, wbcx.tables);
 
@@ -591,7 +595,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         // We may have introduced e.g. `ty::Error`, if inference failed, make sure
         // to mark the `TypeckTables` as tainted in that case, so that downstream
         // users of the tables don't produce extra errors, or worse, ICEs.
-        self.tables.tainted_by_errors |= resolver.replaced_with_error;
+        if resolver.replaced_with_error {
+            // FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
+            self.tables.tainted_by_errors = Some(ErrorReported);
+        }
 
         x
     }
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index 985f66694b6..e17b736058f 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_err, Applicability, StashKey};
+use rustc_errors::{struct_span_err, Applicability, ErrorReported, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -125,7 +125,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                                     owner, def_id,
                                 ),
                             );
-                            if tcx.typeck_tables_of(owner).tainted_by_errors {
+                            if let Some(ErrorReported) =
+                                tcx.typeck_tables_of(owner).tainted_by_errors
+                            {
                                 // Some error in the
                                 // owner fn prevented us from populating
                                 // the `concrete_opaque_types` table.