about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-30 17:01:18 +0000
committerbors <bors@rust-lang.org>2024-01-30 17:01:18 +0000
commitf3d71c9249072413f014b378bb5ea79c8a7dc9a7 (patch)
tree6d35d2fb0886ceb2aa7858c88f7694ba2f1e9801 /compiler/rustc_trait_selection/src
parent5ad7454f7503b6af2800bf4a7c875962cb03f913 (diff)
parent27bc49656462c48f3b98ac1d8ce2b06d446e5ad3 (diff)
downloadrust-f3d71c9249072413f014b378bb5ea79c8a7dc9a7.tar.gz
rust-f3d71c9249072413f014b378bb5ea79c8a7dc9a7.zip
Auto merge of #120496 - GuillaumeGomez:rollup-fmu9jre, r=GuillaumeGomez
Rollup of 11 pull requests

Successful merges:

 - #117906 (Improve display of crate name when hovered)
 - #118533 (Suppress unhelpful diagnostics for unresolved top level attributes)
 - #120293 (Deduplicate more sized errors on call exprs)
 - #120295 (Remove `raw_os_nonzero` feature.)
 - #120310 (adapt test for v0 symbol mangling)
 - #120342 (Remove various `has_errors` or `err_count` uses)
 - #120434 (Revert outdated version of "Add the wasm32-wasi-preview2 target")
 - #120445 (Fix some `Arc` allocator leaks)
 - #120475 (Improve error message when `cargo build` is used to build the compiler)
 - #120476 (Remove some unnecessary check logic for lang items in HIR typeck)
 - #120485 (add missing potential_query_instability for keys and values in hashmap)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs261
3 files changed, 147 insertions, 117 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index c4344758574..0b9fb7b6fbc 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -513,6 +513,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         }
 
         while !vid_map.is_empty() {
+            #[allow(rustc::potential_query_instability)]
             let target = *vid_map.keys().next().expect("Keys somehow empty");
             let deps = vid_map.remove(&target).expect("Entry somehow missing");
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index cdf99870006..69649e36178 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -3292,7 +3292,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     err.help("unsized fn params are gated as an unstable feature");
                 }
             }
-            ObligationCauseCode::SizedReturnType => {
+            ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType => {
                 err.note("the return type of a function must have a statically known size");
             }
             ObligationCauseCode::SizedYieldType => {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 2a09e95b2c5..dee3e14f3c9 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -99,7 +99,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         obligation: PredicateObligation<'tcx>,
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
-    );
+    ) -> ErrorGuaranteed;
 
     fn emit_specialized_closure_kind_error(
         &self,
@@ -107,7 +107,10 @@ pub trait TypeErrCtxtExt<'tcx> {
         trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Option<ErrorGuaranteed>;
 
-    fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool;
+    fn fn_arg_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<(), ErrorGuaranteed>;
 
     fn try_conversion_context(
         &self,
@@ -142,6 +145,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 (
                     span,
                     predicates
+                        .0
                         .iter()
                         .map(|&predicate| ErrorDescriptor { predicate, index: None })
                         .collect(),
@@ -208,10 +212,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
         }
 
+        let mut reported = None;
+
         for from_expansion in [false, true] {
             for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
                 if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
-                    self.report_fulfillment_error(error);
+                    let guar = self.report_fulfillment_error(error);
+                    reported = Some(guar);
                     // We want to ignore desugarings here: spans are equivalent even
                     // if one is the result of a desugaring and the other is not.
                     let mut span = error.obligation.cause.span;
@@ -222,13 +229,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     self.reported_trait_errors
                         .borrow_mut()
                         .entry(span)
-                        .or_default()
+                        .or_insert_with(|| (vec![], guar))
+                        .0
                         .push(error.obligation.predicate);
                 }
             }
         }
 
-        self.dcx().delayed_bug("expected fulfillment errors")
+        // It could be that we don't report an error because we have seen an `ErrorReported` from another source.
+        // We should probably be able to fix most of these, but some are delayed bugs that get a proper error
+        // after this function.
+        reported.unwrap_or_else(|| self.dcx().delayed_bug("failed to report fulfillment errors"))
     }
 
     /// Reports that an overflow has occurred and halts compilation. We
@@ -374,7 +385,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         mut obligation: PredicateObligation<'tcx>,
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
-    ) {
+    ) -> ErrorGuaranteed {
         let tcx = self.tcx;
 
         if tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default()
@@ -384,10 +395,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         let mut span = obligation.cause.span;
-        // FIXME: statically guarantee this by tainting after the diagnostic is emitted
-        self.set_tainted_by_errors(
-            tcx.dcx().span_delayed_bug(span, "`report_selection_error` did not emit an error"),
-        );
 
         let mut err = match *error {
             SelectionError::Unimplemented => {
@@ -412,21 +419,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     kind: _,
                 } = *obligation.cause.code()
                 {
-                    self.report_extra_impl_obligation(
+                    return self.report_extra_impl_obligation(
                         span,
                         impl_item_def_id,
                         trait_item_def_id,
                         &format!("`{}`", obligation.predicate),
                     )
-                    .emit();
-                    return;
+                    .emit()
                 }
 
                 // Report a const-param specific error
                 if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()
                 {
-                    self.report_const_param_not_wf(ty, &obligation).emit();
-                    return;
+                    return self.report_const_param_not_wf(ty, &obligation).emit();
                 }
 
                 let bound_predicate = obligation.predicate.kind();
@@ -436,22 +441,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
                         let trait_ref = trait_predicate.to_poly_trait_ref();
 
-                        if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
-                            return;
+                        if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
+                            return guar;
                         }
 
                         // FIXME(effects)
                         let predicate_is_const = false;
 
-                        if self.dcx().has_errors().is_some()
+                        if let Some(guar) = self.dcx().has_errors()
                             && trait_predicate.references_error()
                         {
-                            return;
+                            return guar;
                         }
-                        if self.fn_arg_obligation(&obligation) {
-                            // Silence redundant errors on binding acccess that are already
-                            // reported on the binding definition (#56607).
-                            return;
+                        // Silence redundant errors on binding acccess that are already
+                        // reported on the binding definition (#56607).
+                        if let Err(guar) = self.fn_arg_obligation(&obligation) {
+                            return guar;
                         }
                         let mut file = None;
                         let (post_message, pre_message, type_def) = self
@@ -515,7 +520,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 trait_ref,
                                 span,
                             ) {
-                                GetSafeTransmuteErrorAndReason::Silent => return,
+                                GetSafeTransmuteErrorAndReason::Silent => return self.dcx().span_delayed_bug(span, "silent safe transmute error"),
                                 GetSafeTransmuteErrorAndReason::Error {
                                     err_msg,
                                     safe_transmute_explanation,
@@ -576,8 +581,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             have_alt_message,
                         ) {
                             self.note_obligation_cause(&mut err, &obligation);
-                            err.emit();
-                            return;
+                            return err.emit();
                         }
 
                         file_note.map(|note| err.note(note));
@@ -680,13 +684,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         }
 
                         if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) {
-                            err.emit();
-                            return;
+                            return err.emit();
                         }
 
                         if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
-                            err.emit();
-                            return;
+                            return err.emit();
                         }
 
                         if is_unsize {
@@ -776,8 +778,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 Some(sym::Debug | sym::Display)
                             )
                         {
-                            err.emit();
-                            return;
+                            return err.emit();
                         }
 
                         err
@@ -912,8 +913,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     found_trait_ref,
                     expected_trait_ref,
                 ) {
-                    Some(err) => err,
-                    None => return,
+                    Ok(err) => err,
+                    Err(guar) => return guar,
                 }
             }
 
@@ -934,15 +935,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
                 match self.report_not_const_evaluatable_error(&obligation, span) {
-                    Some(err) => err,
-                    None => return,
+                    Ok(err) => err,
+                    Err(guar) => return guar,
                 }
             }
 
             // Already reported in the query.
-            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) |
+            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) |
             // Already reported.
-            Overflow(OverflowError::Error(_)) => return,
+            Overflow(OverflowError::Error(guar)) => return guar,
 
             Overflow(_) => {
                 bug!("overflow should be handled before the `report_selection_error` path");
@@ -951,7 +952,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         self.note_obligation_cause(&mut err, &obligation);
         self.point_at_returns_when_relevant(&mut err, &obligation);
-        err.emit();
+        err.emit()
     }
 
     fn emit_specialized_closure_kind_error(
@@ -986,7 +987,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
     }
 
-    fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool {
+    fn fn_arg_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<(), ErrorGuaranteed> {
         if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
             obligation.cause.code()
             && let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id)
@@ -996,12 +1000,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 hir::Path { res: hir::def::Res::Local(hir_id), .. },
             )) = arg.kind
             && let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id)
-            && let Some(preds) = self.reported_trait_errors.borrow().get(&pat.span)
+            && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span)
             && preds.contains(&obligation.predicate)
         {
-            return true;
+            return Err(*guar);
         }
-        false
+        Ok(())
     }
 
     /// When the `E` of the resulting `Result<T, E>` in an expression `foo().bar().baz()?`,
@@ -1323,13 +1327,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
     // `error` occurring implies that `cond` occurs.
     fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
 
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>);
+    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed;
 
     fn report_projection_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         error: &MismatchedProjectionTypes<'tcx>,
-    );
+    ) -> ErrorGuaranteed;
 
     fn maybe_detailed_projection_msg(
         &self,
@@ -1395,7 +1399,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
     ) -> PredicateObligation<'tcx>;
 
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>);
+    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed;
 
     fn predicate_can_apply(
         &self,
@@ -1512,13 +1516,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         span: Span,
         found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
         expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx>>;
+    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>;
 
     fn report_not_const_evaluatable_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
-    ) -> Option<DiagnosticBuilder<'tcx>>;
+    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>;
 }
 
 impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
@@ -1564,7 +1568,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
+    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
         if self.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default()
             == DumpSolverProofTree::OnError
         {
@@ -1572,31 +1576,29 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         match error.code {
-            FulfillmentErrorCode::SelectionError(ref selection_error) => {
-                self.report_selection_error(
+            FulfillmentErrorCode::SelectionError(ref selection_error) => self
+                .report_selection_error(
                     error.obligation.clone(),
                     &error.root_obligation,
                     selection_error,
-                );
-            }
+                ),
             FulfillmentErrorCode::ProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
+                self.report_projection_error(&error.obligation, e)
             }
             FulfillmentErrorCode::Ambiguity { overflow: false } => {
-                self.maybe_report_ambiguity(&error.obligation);
+                self.maybe_report_ambiguity(&error.obligation)
             }
             FulfillmentErrorCode::Ambiguity { overflow: true } => {
-                self.report_overflow_no_abort(error.obligation.clone());
+                self.report_overflow_no_abort(error.obligation.clone())
             }
-            FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
+            FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => self
+                .report_mismatched_types(
                     &error.obligation.cause,
                     expected_found.expected,
                     expected_found.found,
                     *err,
                 )
-                .emit();
-            }
+                .emit(),
             FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => {
                 let mut diag = self.report_mismatched_consts(
                     &error.obligation.cause,
@@ -1620,11 +1622,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         &mut Default::default(),
                     );
                 }
-                diag.emit();
-            }
-            FulfillmentErrorCode::Cycle(ref cycle) => {
-                self.report_overflow_obligation_cycle(cycle);
+                diag.emit()
             }
+            FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle),
         }
     }
 
@@ -1633,11 +1633,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
         error: &MismatchedProjectionTypes<'tcx>,
-    ) {
+    ) -> ErrorGuaranteed {
         let predicate = self.resolve_vars_if_possible(obligation.predicate);
 
-        if predicate.references_error() {
-            return;
+        if let Err(e) = predicate.error_reported() {
+            return e;
         }
 
         self.probe(|_| {
@@ -1802,8 +1802,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 false,
             );
             self.note_obligation_cause(&mut diag, obligation);
-            diag.emit();
-        });
+            diag.emit()
+        })
     }
 
     fn maybe_detailed_projection_msg(
@@ -2341,7 +2341,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
+    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed {
         // Unable to successfully determine, probably means
         // insufficient type information, but could mean
         // ambiguous impls. The latter *ought* to be a
@@ -2361,8 +2361,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 let trait_ref = bound_predicate.rebind(data.trait_ref);
                 debug!(?trait_ref);
 
-                if predicate.references_error() {
-                    return;
+                if let Err(e) = predicate.error_reported() {
+                    return e;
                 }
 
                 // This is kind of a hack: it frequently happens that some earlier
@@ -2381,17 +2381,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // check upstream for type errors and don't add the obligations to
                 // begin with in those cases.
                 if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
-                    if let None = self.tainted_by_errors() {
-                        let err = self.emit_inference_failure_err(
-                            obligation.cause.body_id,
-                            span,
-                            trait_ref.self_ty().skip_binder().into(),
-                            ErrorCode::E0282,
-                            false,
-                        );
-                        err.stash(span, StashKey::MaybeForgetReturn);
+                    match self.tainted_by_errors() {
+                        None => {
+                            let err = self.emit_inference_failure_err(
+                                obligation.cause.body_id,
+                                span,
+                                trait_ref.self_ty().skip_binder().into(),
+                                ErrorCode::E0282,
+                                false,
+                            );
+                            err.stash(span, StashKey::MaybeForgetReturn);
+                            return self.dcx().delayed_bug("stashed error never reported");
+                        }
+                        Some(e) => return e,
                     }
-                    return;
                 }
 
                 // Typically, this ambiguity should only happen if
@@ -2450,19 +2453,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 }
                 if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
-                    if self.tainted_by_errors().is_some() && subst.is_none() {
+                    if let Some(e) = self.tainted_by_errors()
+                        && subst.is_none()
+                    {
                         // If `subst.is_none()`, then this is probably two param-env
                         // candidates or impl candidates that are equal modulo lifetimes.
                         // Therefore, if we've already emitted an error, just skip this
                         // one, since it's not particularly actionable.
                         err.cancel();
-                        return;
+                        return e;
                     }
                     self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
                 } else {
-                    if self.tainted_by_errors().is_some() {
+                    if let Some(e) = self.tainted_by_errors() {
                         err.cancel();
-                        return;
+                        return e;
                     }
                     err.note(format!("cannot satisfy `{predicate}`"));
                     let impl_candidates = self
@@ -2493,7 +2498,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     expr_finder.visit_expr(self.tcx.hir().body(body_id).value);
 
                     if let Some(hir::Expr {
-                        kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
+                        kind:
+                            hir::ExprKind::Call(
+                                hir::Expr {
+                                    kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
+                                    ..
+                                },
+                                _,
+                            )
+                            | hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
                         ..
                     }) = expr_finder.result
                         && let [
@@ -2605,11 +2618,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
-                if arg.references_error()
-                    || self.dcx().has_errors().is_some()
-                    || self.tainted_by_errors().is_some()
-                {
-                    return;
+
+                if let Err(e) = arg.error_reported() {
+                    return e;
+                }
+                if let Some(e) = self.tainted_by_errors() {
+                    return e;
+                }
+                if let Some(e) = self.dcx().has_errors() {
+                    return e;
                 }
 
                 self.emit_inference_failure_err(
@@ -2622,12 +2639,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
 
             ty::PredicateKind::Subtype(data) => {
-                if data.references_error()
-                    || self.dcx().has_errors().is_some()
-                    || self.tainted_by_errors().is_some()
-                {
+                if let Err(e) = data.error_reported() {
+                    return e;
+                }
+                if let Some(e) = self.tainted_by_errors() {
+                    return e;
+                }
+                if let Some(e) = self.dcx().has_errors() {
                     // no need to overload user in such cases
-                    return;
+                    return e;
                 }
                 let SubtypePredicate { a_is_expected: _, a, b } = data;
                 // both must be type variables, or the other would've been instantiated
@@ -2641,8 +2661,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 )
             }
             ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
-                if predicate.references_error() || self.tainted_by_errors().is_some() {
-                    return;
+                if let Err(e) = predicate.error_reported() {
+                    return e;
+                }
+                if let Some(e) = self.tainted_by_errors() {
+                    return e;
                 }
                 let subst = data
                     .projection_ty
@@ -2673,8 +2696,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
 
             ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
-                if predicate.references_error() || self.tainted_by_errors().is_some() {
-                    return;
+                if let Err(e) = predicate.error_reported() {
+                    return e;
+                }
+                if let Some(e) = self.tainted_by_errors() {
+                    return e;
                 }
                 let subst = data.walk().find(|g| g.is_non_region_infer());
                 if let Some(subst) = subst {
@@ -2699,8 +2725,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
             _ => {
-                if self.dcx().has_errors().is_some() || self.tainted_by_errors().is_some() {
-                    return;
+                if let Some(e) = self.tainted_by_errors() {
+                    return e;
+                }
+                if let Some(e) = self.dcx().has_errors() {
+                    // no need to overload user in such cases
+                    return e;
                 }
                 struct_span_code_err!(
                     self.dcx(),
@@ -2713,7 +2743,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
         };
         self.note_obligation_cause(&mut err, obligation);
-        err.emit();
+        err.emit()
     }
 
     fn annotate_source_of_ambiguity(
@@ -3433,16 +3463,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         span: Span,
         found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
         expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
+    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
         let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref);
         let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref);
 
-        if expected_trait_ref.self_ty().references_error() {
-            return None;
-        }
+        expected_trait_ref.self_ty().error_reported()?;
 
         let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else {
-            return None;
+            return Err(self.dcx().delayed_bug("bound vars outside binder"));
         };
 
         let found_did = match *found_trait_ty.kind() {
@@ -3456,7 +3484,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
             // We check closures twice, with obligations flowing in different directions,
             // but we want to complain about them only once.
-            return None;
+            return Err(self.dcx().span_delayed_bug(span, "already_reported"));
         }
 
         let mut not_tupled = false;
@@ -3485,7 +3513,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         // This shouldn't be common unless manually implementing one of the
         // traits manually, but don't make it more confusing when it does
         // happen.
-        Some(
+        Ok(
             if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().coroutine_trait()
                 && not_tupled
             {
@@ -3534,9 +3562,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
+    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
         if !self.tcx.features().generic_const_exprs {
-            self.dcx()
+            let guar = self
+                .dcx()
                 .struct_span_err(span, "constant expression depends on a generic parameter")
                 // FIXME(const_generics): we should suggest to the user how they can resolve this
                 // issue. However, this is currently not actually possible
@@ -3546,7 +3575,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // be reachable.
                 .with_note("this may fail depending on what value the parameter takes")
                 .emit();
-            return None;
+            return Err(guar);
         }
 
         match obligation.predicate.kind().skip_binder() {
@@ -3561,13 +3590,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             )),
                             _ => err.help("consider adding a `where` bound using this expression"),
                         };
-                    Some(err)
+                    Ok(err)
                 }
                 ty::ConstKind::Expr(_) => {
                     let err = self
                         .dcx()
                         .struct_span_err(span, format!("unconstrained generic constant `{ct}`"));
-                    Some(err)
+                    Ok(err)
                 }
                 _ => {
                     bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");