about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs62
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs28
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs79
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs10
13 files changed, 152 insertions, 85 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 466a03e2163..18332d6811d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -52,7 +52,11 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
                 let mut i = 0;
                 while i < candidates.len() {
                     let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
-                        candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j])
+                        candidate_should_be_dropped_in_favor_of(
+                            ecx.tcx(),
+                            &candidates[i],
+                            &candidates[j],
+                        )
                     });
                     if should_drop_i {
                         candidates.swap_remove(i);
@@ -160,12 +164,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 }
 
 fn candidate_should_be_dropped_in_favor_of<'tcx>(
+    tcx: TyCtxt<'tcx>,
     victim: &Candidate<'tcx>,
     other: &Candidate<'tcx>,
 ) -> bool {
     match (victim.source, other.source) {
-        (CandidateSource::ParamEnv(i), CandidateSource::ParamEnv(j)) => i >= j,
+        (CandidateSource::ParamEnv(victim_idx), CandidateSource::ParamEnv(other_idx)) => {
+            victim_idx >= other_idx
+        }
         (_, CandidateSource::ParamEnv(_)) => true,
+        (CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => {
+            tcx.specializes((other_def_id, victim_def_id))
+                && other.result.value.certainty == Certainty::Yes
+        }
         _ => false,
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 83da9db7bff..c0ee1a576e5 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -159,6 +159,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
     fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         let reveal = self.at.param_env.reveal();
         let infcx = self.at.infcx;
+        debug_assert_eq!(ty, infcx.shallow_resolve(ty));
         if !needs_normalization(&ty, reveal) {
             return Ok(ty);
         }
@@ -192,6 +193,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
     fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
         let reveal = self.at.param_env.reveal();
         let infcx = self.at.infcx;
+        debug_assert_eq!(ct, infcx.shallow_resolve(ct));
         if !needs_normalization(&ct, reveal) {
             return Ok(ct);
         }
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 4cfe2bfcb12..1b1285e1b46 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -30,6 +30,7 @@ use std::fmt::Debug;
 use std::iter;
 use std::ops::ControlFlow;
 
+use super::query::evaluate_obligation::InferCtxtExt;
 use super::NormalizeExt;
 
 /// Whether we do the orphan check relative to this crate or
@@ -290,6 +291,20 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
 ) -> bool {
     let infcx = selcx.infcx;
 
+    let obligation_guaranteed_to_fail = move |obligation: &PredicateObligation<'tcx>| {
+        if infcx.next_trait_solver() {
+            infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply())
+        } else {
+            // We use `evaluate_root_obligation` to correctly track
+            // intercrate ambiguity clauses. We do not need this in the
+            // new solver.
+            selcx.evaluate_root_obligation(obligation).map_or(
+                false, // Overflow has occurred, and treat the obligation as possibly holding.
+                |result| !result.may_apply(),
+            )
+        }
+    };
+
     let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates]
         .into_iter()
         .flatten()
@@ -297,12 +312,7 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
             Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
         })
         .chain(obligations)
-        .find(|o| {
-            selcx.evaluate_root_obligation(o).map_or(
-                false, // Overflow has occurred, and treat the obligation as possibly holding.
-                |result| !result.may_apply(),
-            )
-        });
+        .find(obligation_guaranteed_to_fail);
 
     if let Some(failing_obligation) = opt_failing_obligation {
         debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index d5c13a9ccd1..250aa79522c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -30,7 +30,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::traits::solve::Goal;
-use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
+use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
@@ -1152,6 +1152,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
 
+            SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage(
+                &obligation,
+                def_id,
+            ),
+
             TraitNotObjectSafe(did) => {
                 let violations = self.tcx.object_safety_violations(did);
                 report_object_safety_error(self.tcx, span, did, violations)
@@ -1170,16 +1175,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
 
             // Already reported in the query.
-            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;
-            }
+            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) |
             // Already reported.
-            Overflow(OverflowError::Error(_)) => {
-                self.tcx.sess.delay_span_bug(span, "`OverflowError` has been reported");
-                return;
-            }
+            Overflow(OverflowError::Error(_)) => return,
+
             Overflow(_) => {
                 bug!("overflow should be handled before the `report_selection_error` path");
             }
@@ -1471,6 +1470,12 @@ trait InferCtxtPrivExt<'tcx> {
         terr: TypeError<'tcx>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
 
+    fn report_opaque_type_auto_trait_leakage(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        def_id: DefId,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+
     fn report_type_parameter_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
@@ -2646,11 +2651,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
 
             fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() {
+                if let ty::Param(_) = *ty.kind() {
                     let infcx = self.infcx;
                     *self.var_map.entry(ty).or_insert_with(|| {
                         infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
+                            kind: TypeVariableOriginKind::MiscVariable,
                             span: DUMMY_SP,
                         })
                     })
@@ -3192,6 +3197,39 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         )
     }
 
+    fn report_opaque_type_auto_trait_leakage(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        def_id: DefId,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
+            hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
+                format!("opaque type")
+            }
+            hir::OpaqueTyOrigin::TyAlias { .. } => {
+                format!("`{}`", self.tcx.def_path_debug_str(def_id))
+            }
+        };
+        let mut err = self.tcx.sess.struct_span_err(
+            obligation.cause.span,
+            format!("cannot check whether the hidden type of {name} satisfies auto traits"),
+        );
+        err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
+        match self.defining_use_anchor {
+            DefiningAnchor::Bubble | DefiningAnchor::Error => {}
+            DefiningAnchor::Bind(bind) => {
+                err.span_note(
+                    self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
+                    "this item depends on auto traits of the hidden type, \
+                    but may also be registering the hidden type. \
+                    This is not supported right now. \
+                    You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
+                );
+            }
+        };
+        err
+    }
+
     fn report_type_parameter_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 10bd027b684..1e4d30f48b2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -278,7 +278,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
             if let ty::Array(aty, len) = self_ty.kind() {
                 flags.push((sym::_Self, Some("[]".to_string())));
-                let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
+                let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
                 flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
                 if let Some(n) = len {
                     flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 3d96c422256..2d8c260126d 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -528,7 +528,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
 
                         use rustc_hir::def::DefKind;
-                        use ty::ConstKind::Unevaluated;
+                        use ty::Unevaluated;
                         match (c1.kind(), c2.kind()) {
                             (Unevaluated(a), Unevaluated(b))
                                 if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 22d29efa071..9a8e9d97dda 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -447,6 +447,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
         depth: usize,
         obligations: &'a mut Vec<PredicateObligation<'tcx>>,
     ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
+        debug_assert!(!selcx.infcx.next_trait_solver());
         AssocTypeNormalizer {
             selcx,
             param_env,
@@ -1122,6 +1123,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     obligations: &mut Vec<PredicateObligation<'tcx>>,
 ) -> Result<Option<Term<'tcx>>, InProgress> {
     let infcx = selcx.infcx;
+    debug_assert!(!selcx.infcx.next_trait_solver());
     // Don't use the projection cache in intercrate mode -
     // the `infcx` may be re-used between intercrate in non-intercrate
     // mode, which could lead to using incorrect cache results.
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index e29e1b25919..a50644bb709 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -97,6 +97,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                 }
             })
         } else {
+            assert!(!self.intercrate);
             let c_pred = self.canonicalize_query_keep_static(
                 param_env.and(obligation.predicate),
                 &mut _orig_values,
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 42c2c37eca2..979498fb6e6 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,3 +1,4 @@
+use crate::solve;
 use crate::traits::query::NoSolution;
 use crate::traits::wf;
 use crate::traits::ObligationCtxt;
@@ -6,6 +7,7 @@ use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_middle::infer::canonical::CanonicalQueryResponse;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::DUMMY_SP;
@@ -164,19 +166,29 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
 
     // We lazily compute the outlives components as
     // `select_all_or_error` constrains inference variables.
-    let implied_bounds = outlives_bounds
-        .into_iter()
-        .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
-            ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
+    let mut implied_bounds = Vec::new();
+    for ty::OutlivesPredicate(a, r_b) in outlives_bounds {
+        match a.unpack() {
+            ty::GenericArgKind::Lifetime(r_a) => {
+                implied_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a))
+            }
             ty::GenericArgKind::Type(ty_a) => {
-                let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
+                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| NoSolution)?;
+                }
                 let mut components = smallvec![];
                 push_outlives_components(tcx, ty_a, &mut components);
-                implied_bounds_from_components(r_b, components)
+                implied_bounds.extend(implied_bounds_from_components(r_b, components))
             }
             ty::GenericArgKind::Const(_) => unreachable!(),
-        })
-        .collect();
+        }
+    }
 
     Ok(implied_bounds)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 412b601c966..a0329259705 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -388,7 +388,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// `FnPtr`, when we wanted to report that it doesn't implement `Trait`.
     #[instrument(level = "trace", skip(self), ret)]
     fn reject_fn_ptr_impls(
-        &self,
+        &mut self,
         impl_def_id: DefId,
         obligation: &TraitObligation<'tcx>,
         impl_self_ty: Ty<'tcx>,
@@ -464,7 +464,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
                 })),
             );
-            if let Ok(r) = self.infcx.evaluate_obligation(&obligation) {
+            if let Ok(r) = self.evaluate_root_obligation(&obligation) {
                 if !r.may_apply() {
                     return true;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 24e895bc184..744c85ed51f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             AutoImplCandidate => {
-                let data = self.confirm_auto_impl_candidate(obligation);
+                let data = self.confirm_auto_impl_candidate(obligation)?;
                 ImplSource::Builtin(data)
             }
 
@@ -376,12 +376,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn confirm_auto_impl_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> Vec<PredicateObligation<'tcx>> {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!(?obligation, "confirm_auto_impl_candidate");
 
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
-        let types = self.constituent_types_for_ty(self_ty);
-        self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)
+        let types = self.constituent_types_for_ty(self_ty)?;
+        Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
     }
 
     /// See `confirm_auto_impl_candidate`.
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index eb11163de42..26ed1481228 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -34,8 +34,6 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::LateBoundRegionConversionTime;
-use rustc_infer::traits::TraitEngine;
-use rustc_infer::traits::TraitEngineExt;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -312,6 +310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+        debug_assert!(!self.infcx.next_trait_solver());
         // Watch out for overflow. This intentionally bypasses (and does
         // not update) the cache.
         self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
@@ -526,21 +525,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Evaluates whether the obligation `obligation` can be satisfied
     /// and returns an `EvaluationResult`. This is meant for the
     /// *initial* call.
+    ///
+    /// Do not use this directly, use `infcx.evaluate_obligation` instead.
     pub fn evaluate_root_obligation(
         &mut self,
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
+        debug_assert!(!self.infcx.next_trait_solver());
         self.evaluation_probe(|this| {
             let goal =
                 this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
-            let mut result = if this.infcx.next_trait_solver() {
-                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
-            } else {
-                this.evaluate_predicate_recursively(
-                    TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
-                    obligation.clone(),
-                )?
-            };
+            let mut result = this.evaluate_predicate_recursively(
+                TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+                obligation.clone(),
+            )?;
             // If the predicate has done any inference, then downgrade the
             // result to ambiguous.
             if this.infcx.shallow_resolve(goal) != goal {
@@ -587,42 +585,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     where
         I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
     {
-        if self.infcx.next_trait_solver() {
-            self.evaluate_predicates_recursively_in_new_solver(predicates)
-        } else {
-            let mut result = EvaluatedToOk;
-            for mut obligation in predicates {
-                obligation.set_depth_from_parent(stack.depth());
-                let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
-                if let EvaluatedToErr = eval {
-                    // fast-path - EvaluatedToErr is the top of the lattice,
-                    // so we don't need to look on the other predicates.
-                    return Ok(EvaluatedToErr);
-                } else {
-                    result = cmp::max(result, eval);
-                }
+        let mut result = EvaluatedToOk;
+        for mut obligation in predicates {
+            obligation.set_depth_from_parent(stack.depth());
+            let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
+            if let EvaluatedToErr = eval {
+                // fast-path - EvaluatedToErr is the top of the lattice,
+                // so we don't need to look on the other predicates.
+                return Ok(EvaluatedToErr);
+            } else {
+                result = cmp::max(result, eval);
             }
-            Ok(result)
         }
-    }
-
-    /// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled
-    fn evaluate_predicates_recursively_in_new_solver(
-        &mut self,
-        predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self.infcx);
-        fulfill_cx.register_predicate_obligations(self.infcx, predicates);
-        // True errors
-        // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK?
-        if !fulfill_cx.select_where_possible(self.infcx).is_empty() {
-            return Ok(EvaluatedToErr);
-        }
-        if !fulfill_cx.select_all_or_error(self.infcx).is_empty() {
-            return Ok(EvaluatedToAmbig);
-        }
-        // Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot
-        Ok(EvaluatedToOk)
+        Ok(result)
     }
 
     #[instrument(
@@ -636,6 +611,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         previous_stack: TraitObligationStackList<'o, 'tcx>,
         obligation: PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
+        debug_assert!(!self.infcx.next_trait_solver());
         // `previous_stack` stores a `TraitObligation`, while `obligation` is
         // a `PredicateObligation`. These are distinct types, so we can't
         // use any `Option` combinator method that would force them to be
@@ -897,7 +873,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         );
 
                         use rustc_hir::def::DefKind;
-                        use ty::ConstKind::Unevaluated;
+                        use ty::Unevaluated;
                         match (c1.kind(), c2.kind()) {
                             (Unevaluated(a), Unevaluated(b))
                                 if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
@@ -1179,6 +1155,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
+        debug_assert!(!self.infcx.next_trait_solver());
         // In intercrate mode, whenever any of the generics are unbound,
         // there can always be an impl. Even if there are no impls in
         // this crate, perhaps the type would be unified with
@@ -2294,8 +2271,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     fn constituent_types_for_ty(
         &self,
         t: ty::Binder<'tcx, Ty<'tcx>>,
-    ) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
-        match *t.skip_binder().kind() {
+    ) -> Result<ty::Binder<'tcx, Vec<Ty<'tcx>>>, SelectionError<'tcx>> {
+        Ok(match *t.skip_binder().kind() {
             ty::Uint(_)
             | ty::Int(_)
             | ty::Bool
@@ -2359,12 +2336,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             }
 
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                let ty = self.tcx().type_of(def_id);
+                if ty.skip_binder().references_error() {
+                    return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
+                }
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
-                t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
+                t.rebind(vec![ty.subst(self.tcx(), substs)])
             }
-        }
+        })
     }
 
     fn collect_predicates_for_types(
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 86c7fc45ff7..0ae6b181519 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -302,6 +302,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     }
 
     fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> {
+        // Do not normalize `wf` obligations with the new solver.
+        //
+        // The current deep normalization routine with the new solver does not
+        // handle ambiguity and the new solver correctly deals with unnnormalized goals.
+        // If the user relies on normalized types, e.g. for `fn implied_outlives_bounds`,
+        // it is their responsibility to normalize while avoiding ambiguity.
+        if infcx.next_trait_solver() {
+            return self.out;
+        }
+
         let cause = self.cause(traits::WellFormed(None));
         let param_env = self.param_env;
         let mut obligations = Vec::with_capacity(self.out.len());