about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-06-03 09:27:48 -0400
committerMichael Goulet <michael@errs.io>2024-06-03 10:02:08 -0400
commita41c44f21c1a6fd96eb8d68fbdb298610443cff5 (patch)
tree176b96364bf630274f1eb3d65db56865d8bbfa48
parent1e72c7f536bbdf3ed8a0071d28824c071c3722b5 (diff)
downloadrust-a41c44f21c1a6fd96eb8d68fbdb298610443cff5.tar.gz
rust-a41c44f21c1a6fd96eb8d68fbdb298610443cff5.zip
Nits and formatting
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs18
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs10
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs5
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs33
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs2
-rw-r--r--compiler/rustc_macros/src/extension.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs13
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs36
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs32
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs37
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs4
17 files changed, 130 insertions, 142 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 266a80187c5..0cb4b15b127 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -10,7 +10,6 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_span::Span;
-use rustc_trait_selection::solve::deeply_normalize;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::ScrubbedTraitError;
@@ -283,8 +282,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let result = CustomTypeOp::new(
             |ocx| {
-                deeply_normalize(
-                    ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
+                ocx.deeply_normalize(
+                    &ObligationCause::dummy_with_span(self.span),
+                    self.param_env,
                     ty,
                 )
                 .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 594d28eda7a..f7bebc2697d 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -10,7 +10,7 @@ use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::{util, FulfillmentErrorLike};
+use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::util::ExplicitSelf;
@@ -764,10 +764,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     Ok(&*tcx.arena.alloc(remapped_types))
 }
 
-struct ImplTraitInTraitCollector<'a, 'tcx, E>
-where
-    E: FulfillmentErrorLike<'tcx>,
-{
+struct ImplTraitInTraitCollector<'a, 'tcx, E> {
     ocx: &'a ObligationCtxt<'a, 'tcx, E>,
     types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
     span: Span,
@@ -777,7 +774,7 @@ where
 
 impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
 where
-    E: FulfillmentErrorLike<'tcx>,
+    E: 'tcx,
 {
     fn new(
         ocx: &'a ObligationCtxt<'a, 'tcx, E>,
@@ -791,7 +788,7 @@ where
 
 impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
 where
-    E: FulfillmentErrorLike<'tcx>,
+    E: 'tcx,
 {
     fn interner(&self) -> TyCtxt<'tcx> {
         self.ocx.infcx.tcx
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 1e7bb63e6ea..61ac4af0151 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -12,11 +12,8 @@ use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
-use rustc_trait_selection::traits::{
-    self, IsFirstInputType, ScrubbedTraitError, UncoveredTyParams,
-};
+use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
 use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
-use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt};
 
 #[instrument(level = "debug", skip(tcx))]
 pub(crate) fn orphan_check_impl(
@@ -319,13 +316,12 @@ fn orphan_check<'tcx>(
         }
 
         let ty = if infcx.next_trait_solver() {
-            let mut fulfill_cx =
-                <dyn traits::TraitEngine<'tcx, ScrubbedTraitError<'tcx>>>::new(&infcx);
-            infcx
-                .at(&cause, ty::ParamEnv::empty())
-                .structurally_normalize(ty, &mut *fulfill_cx)
-                .map(|ty| infcx.resolve_vars_if_possible(ty))
-                .unwrap_or(ty)
+            ocx.structurally_normalize(
+                &cause,
+                ty::ParamEnv::empty(),
+                infcx.resolve_vars_if_possible(ty),
+            )
+            .unwrap_or(ty)
         } else {
             ty
         };
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 4917f936f4e..d7dd6a1e7cf 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -15,8 +15,8 @@ use crate::infer::canonical::{
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
 use crate::traits::query::NoSolution;
-use crate::traits::{FulfillmentErrorLike, TraitEngine};
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
+use crate::traits::{ScrubbedTraitError, TraitEngine};
 use rustc_data_structures::captures::Captures;
 use rustc_index::Idx;
 use rustc_index::IndexVec;
@@ -50,11 +50,11 @@ impl<'tcx> InferCtxt<'tcx> {
     /// - Finally, if any of the obligations result in a hard error,
     ///   then `Err(NoSolution)` is returned.
     #[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")]
-    pub fn make_canonicalized_query_response<T, E: FulfillmentErrorLike<'tcx>>(
+    pub fn make_canonicalized_query_response<T>(
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
-        fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
     ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -97,11 +97,11 @@ impl<'tcx> InferCtxt<'tcx> {
     /// Helper for `make_canonicalized_query_response` that does
     /// everything up until the final canonicalization.
     #[instrument(skip(self, fulfill_cx), level = "debug")]
-    fn make_query_response<T, E: FulfillmentErrorLike<'tcx>>(
+    fn make_query_response<T>(
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
-        fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
     ) -> Result<QueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 5183d9e2d6e..72c4e1b511e 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -12,8 +12,7 @@ pub use SubregionOrigin::*;
 pub use ValuePairs::*;
 
 use crate::traits::{
-    self, FulfillmentErrorLike, ObligationCause, ObligationInspector, PredicateObligations,
-    TraitEngine,
+    self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
 };
 use error_reporting::TypeErrCtxt;
 use free_regions::RegionRelations;
@@ -738,7 +737,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
 
 impl<'tcx, T> InferOk<'tcx, T> {
     /// Extracts `value`, registering any obligations into `fulfill_cx`.
-    pub fn into_value_registering_obligations<E: FulfillmentErrorLike<'tcx>>(
+    pub fn into_value_registering_obligations<E: 'tcx>(
         self,
         infcx: &InferCtxt<'tcx>,
         fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 1d6875d0f8e..026b2c1b905 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -7,7 +7,32 @@ use rustc_middle::ty::{self, Ty, Upcast};
 
 use super::{ObligationCause, PredicateObligation};
 
-pub trait TraitEngine<'tcx, E: FulfillmentErrorLike<'tcx>>: 'tcx {
+/// A trait error with most of its information removed. This is the error
+/// returned by an `ObligationCtxt` by default, and suitable if you just
+/// want to see if a predicate holds, and don't particularly care about the
+/// error itself (except for if it's an ambiguity or true error).
+///
+/// use `ObligationCtxt::new_with_diagnostics` to get a `FulfillmentError`.
+#[derive(Clone, Debug)]
+pub enum ScrubbedTraitError<'tcx> {
+    /// A real error. This goal definitely does not hold.
+    TrueError,
+    /// An ambiguity. This goal may hold if further inference is done.
+    Ambiguity,
+    /// An old-solver-style cycle error, which will fatal.
+    Cycle(Vec<PredicateObligation<'tcx>>),
+}
+
+impl<'tcx> ScrubbedTraitError<'tcx> {
+    pub fn is_true_error(&self) -> bool {
+        match self {
+            ScrubbedTraitError::TrueError => true,
+            ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false,
+        }
+    }
+}
+
+pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
     /// Requires that `ty` must implement the trait with `def_id` in
     /// the given environment. This trait must not have any type
     /// parameters (except for `Self`).
@@ -73,10 +98,6 @@ pub trait TraitEngine<'tcx, E: FulfillmentErrorLike<'tcx>>: 'tcx {
     ) -> Vec<PredicateObligation<'tcx>>;
 }
 
-pub trait FulfillmentErrorLike<'tcx>: Debug + 'tcx {
-    fn is_true_error(&self) -> bool;
-}
-
-pub trait FromSolverError<'tcx, E>: FulfillmentErrorLike<'tcx> {
+pub trait FromSolverError<'tcx, E>: Debug + 'tcx {
     fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self;
 }
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index e9c2d81aa0a..ca6c6570e07 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -22,7 +22,7 @@ pub use self::ImplSource::*;
 pub use self::SelectionError::*;
 use crate::infer::InferCtxt;
 
-pub use self::engine::{FromSolverError, FulfillmentErrorLike, TraitEngine};
+pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
 pub use self::project::MismatchedProjectionTypes;
 pub(crate) use self::project::UndoLog;
 pub use self::project::{
diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs
index 5377bbdfeab..bbaa477237b 100644
--- a/compiler/rustc_macros/src/extension.rs
+++ b/compiler/rustc_macros/src/extension.rs
@@ -6,6 +6,7 @@ use syn::spanned::Spanned;
 use syn::{
     braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature,
     Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility,
+    WhereClause,
 };
 
 pub(crate) fn extension(
@@ -13,7 +14,7 @@ pub(crate) fn extension(
     input: proc_macro::TokenStream,
 ) -> proc_macro::TokenStream {
     let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr);
-    let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl);
+    let Impl { attrs, generics, self_ty, items, wc } = parse_macro_input!(input as Impl);
     let headers: Vec<_> = items
         .iter()
         .map(|item| match item {
@@ -59,7 +60,7 @@ pub(crate) fn extension(
             #(#headers)*
         }
 
-        impl #generics #trait_ for #self_ty {
+        impl #generics #trait_ for #self_ty #wc {
             #(#items)*
         }
     }
@@ -133,6 +134,7 @@ struct Impl {
     generics: Generics,
     self_ty: Type,
     items: Vec<ImplItem>,
+    wc: Option<WhereClause>,
 }
 
 impl Parse for Impl {
@@ -141,6 +143,7 @@ impl Parse for Impl {
         let _: Token![impl] = input.parse()?;
         let generics = input.parse()?;
         let self_ty = input.parse()?;
+        let wc = input.parse()?;
 
         let content;
         let _brace_token = braced!(content in input);
@@ -149,6 +152,6 @@ impl Parse for Impl {
             items.push(content.parse()?);
         }
 
-        Ok(Impl { attrs, generics, self_ty, items })
+        Ok(Impl { attrs, generics, self_ty, items, wc })
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 3de4aee0927..dc13941e5d7 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -6,8 +6,8 @@ use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
-    self, FromSolverError, FulfillmentErrorLike, MismatchedProjectionTypes, Obligation,
-    ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
+    self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause,
+    ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
 };
 use rustc_middle::bug;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -31,7 +31,7 @@ use super::{Certainty, InferCtxtEvalExt};
 ///
 /// It is also likely that we want to use slightly different datastructures
 /// here as this will have to deal with far more root goals than `evaluate_all`.
-pub struct FulfillmentCtxt<'tcx, E: FulfillmentErrorLike<'tcx>> {
+pub struct FulfillmentCtxt<'tcx, E: 'tcx> {
     obligations: ObligationStorage<'tcx>,
 
     /// The snapshot in which this context was created. Using the context
@@ -93,7 +93,7 @@ impl<'tcx> ObligationStorage<'tcx> {
     }
 }
 
-impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> {
+impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> {
     pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx, E> {
         assert!(
             infcx.next_trait_solver(),
@@ -123,8 +123,9 @@ impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> {
     }
 }
 
-impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> TraitEngine<'tcx, E>
-    for FulfillmentCtxt<'tcx, E>
+impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentCtxt<'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
 {
     #[instrument(level = "trace", skip(self, infcx))]
     fn register_predicate_obligation(
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index dca14e20fb3..1f27978e5a6 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -12,7 +12,6 @@
 use rustc_ast_ir::try_visit;
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_infer::traits::FulfillmentErrorLike as _;
 use rustc_macros::extension;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{inspect, QueryResult};
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 4211129a4e1..c60d1aed415 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -1,3 +1,4 @@
+use std::fmt::Debug;
 use std::marker::PhantomData;
 
 use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt};
@@ -6,7 +7,7 @@ use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::at::At;
 use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, Obligation, TraitEngine};
+use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
@@ -16,14 +17,11 @@ use super::{FulfillmentCtxt, NextSolverError};
 
 /// Deeply normalize all aliases in `value`. This does not handle inference and expects
 /// its input to be already fully resolved.
-pub fn deeply_normalize<
-    'tcx,
+pub fn deeply_normalize<'tcx, T, E>(at: At<'_, 'tcx>, value: T) -> Result<T, Vec<E>>
+where
     T: TypeFoldable<TyCtxt<'tcx>>,
     E: FromSolverError<'tcx, NextSolverError<'tcx>>,
->(
-    at: At<'_, 'tcx>,
-    value: T,
-) -> Result<T, Vec<E>> {
+{
     assert!(!value.has_escaping_bound_vars());
     deeply_normalize_with_skipped_universes(at, value, vec![])
 }
@@ -34,15 +32,15 @@ pub fn deeply_normalize<
 /// Additionally takes a list of universes which represents the binders which have been
 /// entered before passing `value` to the function. This is currently needed for
 /// `normalize_erasing_regions`, which skips binders as it walks through a type.
-pub fn deeply_normalize_with_skipped_universes<
-    'tcx,
-    T: TypeFoldable<TyCtxt<'tcx>>,
-    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
->(
+pub fn deeply_normalize_with_skipped_universes<'tcx, T, E>(
     at: At<'_, 'tcx>,
     value: T,
     universes: Vec<Option<UniverseIndex>>,
-) -> Result<T, Vec<E>> {
+) -> Result<T, Vec<E>>
+where
+    T: TypeFoldable<TyCtxt<'tcx>>,
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     let fulfill_cx = FulfillmentCtxt::new(at.infcx);
     let mut folder =
         NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
@@ -50,7 +48,7 @@ pub fn deeply_normalize_with_skipped_universes<
     value.try_fold_with(&mut folder)
 }
 
-struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> {
+struct NormalizationFolder<'me, 'tcx, E> {
     at: At<'me, 'tcx>,
     fulfill_cx: FulfillmentCtxt<'tcx, E>,
     depth: usize,
@@ -58,7 +56,10 @@ struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> {
     _errors: PhantomData<E>,
 }
 
-impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<'_, 'tcx, E> {
+impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
         assert!(matches!(alias_ty.kind(), ty::Alias(..)));
 
@@ -150,8 +151,9 @@ impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<
     }
 }
 
-impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> FallibleTypeFolder<TyCtxt<'tcx>>
-    for NormalizationFolder<'_, 'tcx, E>
+impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>> + Debug,
 {
     type Error = Vec<E>;
 
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 397f9cf2638..811f61d2bf3 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -21,7 +21,6 @@ use rustc_infer::infer::canonical::{
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::RegionResolutionError;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_infer::traits::FulfillmentErrorLike;
 use rustc_macros::extension;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::traits::query::NoSolution;
@@ -32,10 +31,9 @@ use rustc_middle::ty::Variance;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 #[extension(pub trait TraitEngineExt<'tcx, E>)]
-impl<
-    'tcx,
+impl<'tcx, E> dyn TraitEngine<'tcx, E>
+where
     E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
-> dyn TraitEngine<'tcx, E>
 {
     fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
         if infcx.next_trait_solver() {
@@ -73,7 +71,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> {
 
 impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E>
 where
-    E: FulfillmentErrorLike<'tcx>,
+    E: 'tcx,
 {
     pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
         self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
@@ -231,7 +229,20 @@ where
     ) -> Vec<RegionResolutionError<'tcx>> {
         self.infcx.resolve_regions(outlives_env)
     }
+}
+
+impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
+    pub fn assumed_wf_types_and_report_errors(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        def_id: LocalDefId,
+    ) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
+        self.assumed_wf_types(param_env, def_id)
+            .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
+    }
+}
 
+impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> {
     pub fn make_canonicalized_query_response<T>(
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
@@ -249,17 +260,6 @@ where
     }
 }
 
-impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
-    pub fn assumed_wf_types_and_report_errors(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        def_id: LocalDefId,
-    ) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
-        self.assumed_wf_types(param_env, def_id)
-            .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
-    }
-}
-
 impl<'tcx, E> ObligationCtxt<'_, 'tcx, E>
 where
     E: FromSolverError<'tcx, NextSolverError<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 59802a26043..8ab9d5754c0 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -6,7 +6,7 @@ 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_infer::infer::DefineOpaqueTypes;
-use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, ProjectionCacheKey};
+use rustc_infer::traits::{FromSolverError, ProjectionCacheKey};
 use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::ErrorHandled;
@@ -50,7 +50,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
 /// along. Once all type inference constraints have been generated, the
 /// method `select_all_or_error` can be used to report any remaining
 /// ambiguous cases as errors.
-pub struct FulfillmentContext<'tcx, E: FulfillmentErrorLike<'tcx>> {
+pub struct FulfillmentContext<'tcx, E: 'tcx> {
     /// A list of all obligations that have been registered with this
     /// fulfillment context.
     predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
@@ -78,7 +78,10 @@ pub struct PendingPredicateObligation<'tcx> {
 #[cfg(target_pointer_width = "64")]
 rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
 
-impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'tcx, E> {
+impl<'tcx, E> FulfillmentContext<'tcx, E>
+where
+    E: FromSolverError<'tcx, OldSolverError<'tcx>>,
+{
     /// Creates a new fulfillment context.
     pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> {
         assert!(
@@ -106,8 +109,11 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'t
         // FIXME: if we kept the original cache key, we could mark projection
         // obligations as complete for the projection cache here.
 
-        let errors: Vec<E> =
-            outcome.errors.into_iter().map(|err| E::from_solver_error(infcx, err)).collect();
+        let errors: Vec<E> = outcome
+            .errors
+            .into_iter()
+            .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
+            .collect();
 
         debug!(
             "select({} predicates remaining, {} errors) done",
@@ -119,8 +125,9 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'t
     }
 }
 
-impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E>
-    for FulfillmentContext<'tcx, E>
+impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentContext<'tcx, E>
+where
+    E: FromSolverError<'tcx, OldSolverError<'tcx>>,
 {
     #[inline]
     fn register_predicate_obligation(
@@ -144,7 +151,7 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E>
         self.predicates
             .to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
             .into_iter()
-            .map(|err| E::from_solver_error(infcx, err))
+            .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
             .collect()
     }
 
@@ -843,22 +850,25 @@ fn args_infer_vars<'a, 'tcx>(
         .filter_map(TyOrConstInferVar::maybe_from_generic_arg)
 }
 
-pub type OldSolverError<'tcx> = Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>;
+#[derive(Debug)]
+pub struct OldSolverError<'tcx>(
+    Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
+);
 
 impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> {
     fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
-        let mut iter = error.backtrace.into_iter();
+        let mut iter = error.0.backtrace.into_iter();
         let obligation = iter.next().unwrap().obligation;
         // The root obligation is the last item in the backtrace - if there's only
         // one item, then it's the same as the main obligation
         let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
-        FulfillmentError::new(obligation, error.error, root_obligation)
+        FulfillmentError::new(obligation, error.0.error, root_obligation)
     }
 }
 
 impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> {
     fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
-        match error.error {
+        match error.0.error {
             FulfillmentErrorCode::Select(_)
             | FulfillmentErrorCode::Project(_)
             | FulfillmentErrorCode::Subtype(_, _)
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 9aaa8adbd67..d918945dbed 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -71,37 +71,6 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh
 
 pub use rustc_infer::traits::*;
 
-/// A trait error with most of its information removed. This is the error
-/// returned by an [`ObligationCtxt`] by default, and suitable if you just
-/// want to see if a predicate holds, and don't particularly care about the
-/// error itself (except for if it's an ambiguity or true error).
-///
-/// use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`].
-#[derive(Clone, Debug)]
-pub enum ScrubbedTraitError<'tcx> {
-    /// A real error. This goal definitely does not hold.
-    TrueError,
-    /// An ambiguity. This goal may hold if further inference is done.
-    Ambiguity,
-    /// An old-solver-style cycle error, which will fatal.
-    Cycle(Vec<PredicateObligation<'tcx>>),
-}
-
-impl<'tcx> ScrubbedTraitError<'tcx> {
-    fn is_true_error(&self) -> bool {
-        match self {
-            ScrubbedTraitError::TrueError => true,
-            ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false,
-        }
-    }
-}
-
-impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError<'tcx> {
-    fn is_true_error(&self) -> bool {
-        self.is_true_error()
-    }
-}
-
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>,
@@ -133,12 +102,6 @@ impl<'tcx> FulfillmentError<'tcx> {
     }
 }
 
-impl<'tcx> FulfillmentErrorLike<'tcx> for FulfillmentError<'tcx> {
-    fn is_true_error(&self) -> bool {
-        self.is_true_error()
-    }
-}
-
 impl<'tcx> Debug for FulfillmentError<'tcx> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 4e5ca2ee92e..db30521d776 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -46,14 +46,15 @@ impl<'tcx> At<'_, 'tcx> {
     /// existing fulfillment context in the old solver. Once we also eagerly prove goals with
     /// the old solver or have removed the old solver, remove `traits::fully_normalize` and
     /// rename this function to `At::fully_normalize`.
-    fn deeply_normalize<
-        T: TypeFoldable<TyCtxt<'tcx>>,
-        E: FromSolverError<'tcx, NextSolverError<'tcx>>,
-    >(
+    fn deeply_normalize<T, E>(
         self,
         value: T,
         fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
-    ) -> Result<T, Vec<E>> {
+    ) -> Result<T, Vec<E>>
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+        E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+    {
         if self.infcx.next_trait_solver() {
             crate::solve::deeply_normalize(self, value)
         } else {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 54fa0749618..b38841db923 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,8 +1,6 @@
-use crate::solve;
 use crate::traits::query::NoSolution;
 use crate::traits::wf;
 use crate::traits::ObligationCtxt;
-use crate::traits::ScrubbedTraitError;
 
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
@@ -263,11 +261,9 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
                 let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
                 // Need to manually normalize in the new solver as `wf::obligations` does not.
                 if ocx.infcx.next_trait_solver() {
-                    ty_a = solve::deeply_normalize(
-                        ocx.infcx.at(&ObligationCause::dummy(), param_env),
-                        ty_a,
-                    )
-                    .map_err(|_errs: Vec<ScrubbedTraitError<'tcx>>| NoSolution)?;
+                    ty_a = ocx
+                        .deeply_normalize(&ObligationCause::dummy(), param_env, ty_a)
+                        .map_err(|_| NoSolution)?;
                 }
                 let mut components = smallvec![];
                 push_outlives_components(tcx, ty_a, &mut components);
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index a160fc033a2..9d657ade86b 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -1,5 +1,5 @@
 use rustc_infer::infer::at::At;
-use rustc_infer::traits::{FulfillmentErrorLike, TraitEngine};
+use rustc_infer::traits::TraitEngine;
 use rustc_macros::extension;
 use rustc_middle::ty::{self, Ty};
 
@@ -7,7 +7,7 @@ use crate::traits::{NormalizeExt, Obligation};
 
 #[extension(pub trait StructurallyNormalizeExt<'tcx>)]
 impl<'tcx> At<'_, 'tcx> {
-    fn structurally_normalize<E: FulfillmentErrorLike<'tcx>>(
+    fn structurally_normalize<E: 'tcx>(
         &self,
         ty: Ty<'tcx>,
         fulfill_cx: &mut dyn TraitEngine<'tcx, E>,