about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs10
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs111
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs40
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs79
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/opaques.rs20
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs10
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr23
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.rs4
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr4
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.rs2
-rw-r--r--tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs5
-rw-r--r--tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.stderr14
-rw-r--r--tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr13
-rw-r--r--tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr13
-rw-r--r--tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.current.stderr (renamed from tests/ui/type-alias-impl-trait/self-referential-2.stderr)2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr (renamed from tests/ui/type-alias-impl-trait/type_of_a_let.stderr)4
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.rs8
23 files changed, 186 insertions, 214 deletions
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index c1af4b5983e..629c2f2a971 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -304,6 +304,10 @@ fn typeck_with_fallback<'tcx>(
 
     let typeck_results = fcx.resolve_type_vars_in_body(body);
 
+    // We clone the defined opaque types during writeback in the new solver
+    // because we have to use them during normalization.
+    let _ = fcx.infcx.take_opaque_types();
+
     // Consistency check our TypeckResults instance can hold all ItemLocalIds
     // it will need to hold.
     assert_eq!(typeck_results.hir_owner, id.owner);
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 5ce80ef5c10..d84bce09ecb 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -562,7 +562,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn visit_opaque_types(&mut self) {
-        let opaque_types = self.fcx.infcx.take_opaque_types();
+        // We clone the opaques instead of stealing them here as they are still used for
+        // normalization in the next generation trait solver.
+        //
+        // FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
+        // at the end of typeck. While this seems unlikely to happen in practice this
+        // should still get fixed. Either by preventing writeback from defining new opaque
+        // types or by using this function at the end of writeback and running it as a
+        // fixpoint.
+        let opaque_types = self.fcx.infcx.clone_opaque_types();
         for (opaque_type_key, decl) in opaque_types {
             let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
             let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 0bf4598608f..2caf3b3cc93 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1325,6 +1325,12 @@ impl<'tcx> InferCtxt<'tcx> {
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
     }
 
+    #[instrument(level = "debug", skip(self), ret)]
+    pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
+        debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error);
+        self.inner.borrow().opaque_type_storage.opaque_types.clone()
+    }
+
     pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
         self.resolve_vars_if_possible(t).to_string()
     }
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index c05c9961750..81be5c09164 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -3,33 +3,27 @@
 //! of our more general approach to "lazy normalization".
 //!
 //! This is done by first normalizing both sides of the goal, ending up in
-//! either a concrete type, rigid projection, opaque, or an infer variable.
+//! either a concrete type, rigid alias, or an infer variable.
 //! These are related further according to the rules below:
 //!
-//! (1.) If we end up with a rigid projection and a rigid projection, then we
-//! relate those projections structurally.
+//! (1.) If we end up with two rigid aliases, then we relate them structurally.
 //!
-//! (2.) If we end up with a rigid projection and an alias, then the opaque will
-//! have its hidden type defined to be that rigid projection.
-//!
-//! (3.) If we end up with an opaque and an opaque, then we assemble two
-//! candidates, one defining the LHS to be the hidden type of the RHS, and vice
-//! versa.
-//!
-//! (4.) If we end up with an infer var and an opaque or rigid projection, then
+//! (2.) If we end up with an infer var and a rigid alias, then
 //! we assign the alias to the infer var.
 //!
-//! (5.) If we end up with an opaque and a rigid (non-projection) type, then we
-//! define the hidden type of the opaque to be the rigid type.
-//!
-//! (6.) Otherwise, if we end with two rigid (non-projection) or infer types,
+//! (3.) Otherwise, if we end with two rigid (non-projection) or infer types,
 //! relate them structurally.
+//!
+//! Subtle: when relating an opaque to another type, we emit a
+//! `NormalizesTo(opaque, ?fresh_var)` goal when trying to normalize the opaque.
+//! This nested goal starts out as ambiguous and does not actually define the opaque.
+//! However, if `?fresh_var` ends up geteting equated to another type, we retry the
+//! `NormalizesTo` goal, at which point the opaque is actually defined.
 
 use super::{EvalCtxt, GoalSource};
-use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
-use rustc_middle::ty;
+use rustc_middle::ty::{self, Ty};
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
@@ -59,37 +53,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
 
-            (Some(alias), None) => {
+            (Some(_), None) => {
                 if rhs.is_infer() {
                     self.relate(param_env, lhs, variance, rhs)?;
                     self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                } else if alias.is_opaque(tcx) {
-                    // FIXME: This doesn't account for variance.
-                    self.define_opaque(param_env, alias, rhs)
                 } else {
                     Err(NoSolution)
                 }
             }
-            (None, Some(alias)) => {
+            (None, Some(_)) => {
                 if lhs.is_infer() {
                     self.relate(param_env, lhs, variance, rhs)?;
                     self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                } else if alias.is_opaque(tcx) {
-                    // FIXME: This doesn't account for variance.
-                    self.define_opaque(param_env, alias, lhs)
                 } else {
                     Err(NoSolution)
                 }
             }
 
             (Some(alias_lhs), Some(alias_rhs)) => {
-                self.relate_rigid_alias_or_opaque(param_env, alias_lhs, variance, alias_rhs)
+                self.relate(param_env, alias_lhs, variance, alias_rhs)?;
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
         }
     }
 
     // FIXME: This needs a name that reflects that it's okay to bottom-out with an inference var.
-    /// Normalize the `term` to equate it later. This does not define opaque types.
+    /// Normalize the `term` to equate it later.
     #[instrument(level = "debug", skip(self, param_env), ret)]
     fn try_normalize_term(
         &mut self,
@@ -98,10 +87,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     ) -> Result<Option<ty::Term<'tcx>>, NoSolution> {
         match term.unpack() {
             ty::TermKind::Ty(ty) => {
-                // We do no define opaque types here but instead do so in `relate_rigid_alias_or_opaque`.
-                Ok(self
-                    .try_normalize_ty_recur(param_env, DefineOpaqueTypes::No, 0, ty)
-                    .map(Into::into))
+                Ok(self.try_normalize_ty_recur(param_env, 0, ty).map(Into::into))
             }
             ty::TermKind::Const(_) => {
                 if let Some(alias) = term.to_alias_ty(self.tcx()) {
@@ -119,51 +105,34 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
-    fn define_opaque(
+    fn try_normalize_ty_recur(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
-        opaque: ty::AliasTy<'tcx>,
-        term: ty::Term<'tcx>,
-    ) -> QueryResult<'tcx> {
-        self.add_goal(
-            GoalSource::Misc,
-            Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias: opaque, term }),
-        );
-        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-    }
-
-    fn relate_rigid_alias_or_opaque(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        lhs: ty::AliasTy<'tcx>,
-        variance: ty::Variance,
-        rhs: ty::AliasTy<'tcx>,
-    ) -> QueryResult<'tcx> {
-        let tcx = self.tcx();
-        let mut candidates = vec![];
-        if lhs.is_opaque(tcx) {
-            candidates.extend(
-                self.probe_misc_candidate("define-lhs-opaque")
-                    .enter(|ecx| ecx.define_opaque(param_env, lhs, rhs.to_ty(tcx).into())),
-            );
+        depth: usize,
+        ty: Ty<'tcx>,
+    ) -> Option<Ty<'tcx>> {
+        if !self.tcx().recursion_limit().value_within_limit(depth) {
+            return None;
         }
 
-        if rhs.is_opaque(tcx) {
-            candidates.extend(
-                self.probe_misc_candidate("define-rhs-opaque")
-                    .enter(|ecx| ecx.define_opaque(param_env, rhs, lhs.to_ty(tcx).into())),
-            );
-        }
-
-        candidates.extend(self.probe_misc_candidate("args-relate").enter(|ecx| {
-            ecx.relate(param_env, lhs, variance, rhs)?;
-            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-        }));
+        let ty::Alias(_, alias) = *ty.kind() else {
+            return Some(ty);
+        };
 
-        if let Some(result) = self.try_merge_responses(&candidates) {
-            Ok(result)
-        } else {
-            self.flounder(&candidates)
+        match self.commit_if_ok(|this| {
+            let normalized_ty = this.next_ty_infer();
+            let normalizes_to_goal = Goal::new(
+                this.tcx(),
+                param_env,
+                ty::NormalizesTo { alias, term: normalized_ty.into() },
+            );
+            this.add_goal(GoalSource::Misc, normalizes_to_goal);
+            this.try_evaluate_added_goals()?;
+            let ty = this.resolve_vars_if_possible(normalized_ty);
+            Ok(this.try_normalize_ty_recur(param_env, depth + 1, ty))
+        }) {
+            Ok(ty) => ty,
+            Err(NoSolution) => Some(ty),
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 6833d2ae330..733c415ead5 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -276,11 +276,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         &mut self,
         goal: Goal<'tcx, G>,
     ) -> Vec<Candidate<'tcx>> {
-        let Some(normalized_self_ty) =
-            self.try_normalize_ty(goal.param_env, goal.predicate.self_ty())
+        let Ok(normalized_self_ty) =
+            self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
         else {
-            debug!("overflow while evaluating self type");
-            return self.forced_ambiguity(MaybeCause::Overflow);
+            return vec![];
         };
 
         if normalized_self_ty.is_ty_var() {
@@ -635,19 +634,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             return;
         }
 
-        match self.try_normalize_ty(goal.param_env, alias_ty.self_ty()) {
-            // Recurse on the self type of the projection.
-            Some(next_self_ty) => {
-                self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates);
-            }
-            // Bail if we overflow when normalizing, adding an ambiguous candidate.
-            None => {
-                if let Ok(result) =
-                    self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
-                {
-                    candidates.push(Candidate { source: CandidateSource::AliasBound, result });
-                }
+        // Recurse on the self type of the projection.
+        match self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) {
+            Ok(next_self_ty) => {
+                self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates)
             }
+            Err(NoSolution) => {}
         }
     }
 
@@ -857,19 +849,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let tcx = self.tcx();
         let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| {
             let trait_ref = goal.predicate.trait_ref(tcx);
-            #[derive(Debug)]
-            struct Overflow;
-            let lazily_normalize_ty = |ty| match ecx.try_normalize_ty(goal.param_env, ty) {
-                Some(ty) => Ok(ty),
-                None => Err(Overflow),
-            };
+            let lazily_normalize_ty = |ty| ecx.structurally_normalize_ty(goal.param_env, ty);
 
-            match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty) {
-                Err(Overflow) => {
-                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW)
-                }
-                Ok(Ok(())) => Err(NoSolution),
-                Ok(Err(_)) => {
+            match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty)? {
+                Ok(()) => Err(NoSolution),
+                Err(_) => {
                     ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index a7330136fe7..94a3cef8ad1 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -15,15 +15,13 @@
 //! about it on zulip.
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
-use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::infer::canonical::CanonicalVarInfos;
 use rustc_middle::traits::solve::{
     CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, IsNormalizesToHack,
     QueryResult, Response,
 };
-use rustc_middle::traits::Reveal;
-use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, UniverseIndex};
+use rustc_middle::ty::{self, AliasRelationDirection, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{
     CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
 };
@@ -267,71 +265,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
     }
 
-    /// Normalize a type when it is structually matched on.
+    /// Normalize a type for when it is structurally matched on.
     ///
-    /// In nearly all cases this function must be used before matching on a type.
+    /// This function is necessary in nearly all cases before matching on a type.
     /// Not doing so is likely to be incomplete and therefore unsound during
     /// coherence.
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_normalize_ty(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        self.try_normalize_ty_recur(param_env, DefineOpaqueTypes::Yes, 0, ty)
-    }
-
-    fn try_normalize_ty_recur(
+    fn structurally_normalize_ty(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
-        define_opaque_types: DefineOpaqueTypes,
-        depth: usize,
         ty: Ty<'tcx>,
-    ) -> Option<Ty<'tcx>> {
-        if !self.tcx().recursion_limit().value_within_limit(depth) {
-            return None;
-        }
-
-        let ty::Alias(kind, alias) = *ty.kind() else {
-            return Some(ty);
-        };
-
-        // We do no always define opaque types eagerly to allow non-defining uses
-        // in the defining scope. However, if we can unify this opaque to an existing
-        // opaque, then we should attempt to eagerly reveal the opaque, and we fall
-        // through.
-        if let DefineOpaqueTypes::No = define_opaque_types
-            && let Reveal::UserFacing = param_env.reveal()
-            && let ty::Opaque = kind
-            && let Some(def_id) = alias.def_id.as_local()
-            && self.can_define_opaque_ty(def_id)
-        {
-            if self
-                .unify_existing_opaque_tys(
-                    param_env,
-                    OpaqueTypeKey { def_id, args: alias.args },
-                    self.next_ty_infer(),
-                )
-                .is_empty()
-            {
-                return Some(ty);
-            }
-        }
-
-        match self.commit_if_ok(|this| {
-            let normalized_ty = this.next_ty_infer();
-            let normalizes_to_goal = Goal::new(
-                this.tcx(),
+    ) -> Result<Ty<'tcx>, NoSolution> {
+        if let ty::Alias(..) = ty.kind() {
+            let normalized_ty = self.next_ty_infer();
+            let alias_relate_goal = Goal::new(
+                self.tcx(),
                 param_env,
-                ty::NormalizesTo { alias, term: normalized_ty.into() },
+                ty::PredicateKind::AliasRelate(
+                    ty.into(),
+                    normalized_ty.into(),
+                    AliasRelationDirection::Equate,
+                ),
             );
-            this.add_goal(GoalSource::Misc, normalizes_to_goal);
-            this.try_evaluate_added_goals()?;
-            let ty = this.resolve_vars_if_possible(normalized_ty);
-            Ok(this.try_normalize_ty_recur(param_env, define_opaque_types, depth + 1, ty))
-        }) {
-            Ok(ty) => ty,
-            Err(NoSolution) => Some(ty),
+            self.add_goal(GoalSource::Misc, alias_relate_goal);
+            self.try_evaluate_added_goals()?;
+            Ok(self.resolve_vars_if_possible(normalized_ty))
+        } else {
+            Ok(ty)
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaques.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaques.rs
index b5d1aa06e4e..356c3776c04 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaques.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaques.rs
@@ -58,21 +58,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     }
                 }
 
-                let expected = match self.try_normalize_ty(goal.param_env, expected) {
-                    Some(ty) => {
-                        if ty.is_ty_var() {
-                            return self.evaluate_added_goals_and_make_canonical_response(
-                                Certainty::AMBIGUOUS,
-                            );
-                        } else {
-                            ty
-                        }
-                    }
-                    None => {
-                        return self
-                            .evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
-                    }
-                };
+                let expected = self.structurally_normalize_ty(goal.param_env, expected)?;
+                if expected.is_ty_var() {
+                    return self
+                        .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
+                }
 
                 // Otherwise, define a new opaque type
                 self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 7a466241bfa..eacdd9fde51 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -584,11 +584,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             let a_ty = goal.predicate.self_ty();
             // We need to normalize the b_ty since it's matched structurally
             // in the other functions below.
-            let b_ty = match ecx
-                .try_normalize_ty(goal.param_env, goal.predicate.trait_ref.args.type_at(1))
-            {
-                Some(b_ty) => b_ty,
-                None => return vec![misc_candidate(ecx, Certainty::OVERFLOW)],
+            let Ok(b_ty) = ecx.structurally_normalize_ty(
+                goal.param_env,
+                goal.predicate.trait_ref.args.type_at(1),
+            ) else {
+                return vec![];
             };
 
             let goal = goal.with(ecx.tcx(), (a_ty, b_ty));
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
new file mode 100644
index 00000000000..fee3b86034a
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
@@ -0,0 +1,23 @@
+error[E0282]: type annotations needed
+  --> $DIR/recursive-coroutine-boxed.rs:10:23
+   |
+LL |         let mut gen = Box::pin(foo());
+   |                       ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
+...
+LL |         let mut r = gen.as_mut().resume(());
+   |                         ------ type must be known at this point
+   |
+help: consider specifying the generic argument
+   |
+LL |         let mut gen = Box::<T>::pin(foo());
+   |                          +++++
+
+error[E0282]: type annotations needed
+  --> $DIR/recursive-coroutine-boxed.rs:10:32
+   |
+LL |         let mut gen = Box::pin(foo());
+   |                                ^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
index b9291f07e21..3f677986c13 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
@@ -1,5 +1,5 @@
-// check-pass
 // revisions: current next
+//[current] check-pass
 //[next] compile-flags: -Znext-solver
 #![feature(coroutines, coroutine_trait)]
 
@@ -8,6 +8,8 @@ use std::ops::{Coroutine, CoroutineState};
 fn foo() -> impl Coroutine<Yield = (), Return = ()> {
     || {
         let mut gen = Box::pin(foo());
+        //[next]~^ ERROR type annotations needed
+        //[next]~| ERROR type annotations needed
         let mut r = gen.as_mut().resume(());
         while let CoroutineState::Yielded(v) = r {
             yield v;
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
index e49d1d18b0c..69328e20583 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
@@ -1,8 +1,8 @@
-error[E0284]: type annotations needed: cannot satisfy `A <: B`
+error[E0284]: type annotations needed: cannot satisfy `A == B`
   --> $DIR/two_tait_defining_each_other2.rs:11:5
    |
 LL |     x // B's hidden type is A (opaquely)
-   |     ^ cannot satisfy `A <: B`
+   |     ^ cannot satisfy `A == B`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index 8a79af19776..b2f768f4dcd 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -10,7 +10,7 @@ trait Foo {}
 fn muh(x: A) -> B {
     x // B's hidden type is A (opaquely)
     //[current]~^ ERROR opaque type's hidden type cannot be another opaque type
-    //[next]~^^ ERROR type annotations needed: cannot satisfy `A <: B`
+    //[next]~^^ ERROR type annotations needed: cannot satisfy `A == B`
 }
 
 struct Bar;
diff --git a/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs b/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs
index 08f26686b2f..f9f5a1dc24d 100644
--- a/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs
+++ b/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.rs
@@ -1,9 +1,10 @@
 // compile-flags: -Znext-solver
-// check-pass
-
+// FIXME(-Znext-solver): This test is currently broken because the `deduce_closure_signature`
+// is unable to look at nested obligations.
 trait Foo {
     fn test() -> impl Fn(u32) -> u32 {
         |x| x.count_ones()
+        //~^ ERROR type annotations needed
     }
 }
 
diff --git a/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.stderr b/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.stderr
new file mode 100644
index 00000000000..3d7cd1af467
--- /dev/null
+++ b/tests/ui/traits/next-solver/deduce-closure-signature-after-normalization.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/deduce-closure-signature-after-normalization.rs:6:10
+   |
+LL |         |x| x.count_ones()
+   |          ^  - type must be known at this point
+   |
+help: consider giving this closure parameter an explicit type
+   |
+LL |         |x: /* Type */| x.count_ones()
+   |           ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr
index bafc4ba18a7..158fefd1538 100644
--- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr
+++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr
@@ -1,16 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
+error[E0284]: type annotations needed: cannot satisfy `Foo == _`
   --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
    |
 LL |     needs_send::<Foo>();
-   |                  ^^^
-   |
-   = note: cannot satisfy `Foo: Send`
-note: required by a bound in `needs_send`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
-   |
-LL | fn needs_send<T: Send>() {}
-   |                  ^^^^ required by this bound in `needs_send`
+   |                  ^^^ cannot satisfy `Foo == _`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr
index bafc4ba18a7..158fefd1538 100644
--- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr
+++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr
@@ -1,16 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
+error[E0284]: type annotations needed: cannot satisfy `Foo == _`
   --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
    |
 LL |     needs_send::<Foo>();
-   |                  ^^^
-   |
-   = note: cannot satisfy `Foo: Send`
-note: required by a bound in `needs_send`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
-   |
-LL | fn needs_send<T: Send>() {}
-   |                  ^^^^ required by this bound in `needs_send`
+   |                  ^^^ cannot satisfy `Foo == _`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs
index ef0360248b5..9720a653e2b 100644
--- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs
@@ -13,7 +13,7 @@ fn needs_send<T: Send>() {}
 
 fn test(_: Foo) {
     needs_send::<Foo>();
-    //~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
+    //~^ ERROR type annotations needed: cannot satisfy `Foo == _`
 }
 
 fn defines(_: Foo) {
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
index ab57812ba9b..019e01a07d3 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `i32` with `Foo`
-  --> $DIR/self-referential-2.rs:6:13
+  --> $DIR/self-referential-2.rs:9:13
    |
 LL | fn bar() -> Bar {
    |             ^^^ no implementation for `i32 == Foo`
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs
index 8781196c39f..3a765a2e3ef 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs
@@ -1,10 +1,13 @@
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+//[next] check-pass
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl std::fmt::Debug;
 type Bar = impl PartialEq<Foo>;
 
 fn bar() -> Bar {
-    42_i32 //~^ ERROR can't compare `i32` with `Foo`
+    42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr
new file mode 100644
index 00000000000..b380dc66f03
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr
@@ -0,0 +1,15 @@
+error[E0284]: type annotations needed: cannot satisfy `Foo == _`
+  --> $DIR/type-alias-impl-trait-tuple.rs:21:24
+   |
+LL |         Blah { my_foo: make_foo(), my_u8: 12 }
+   |                        ^^^^^^^^^^ cannot satisfy `Foo == _`
+
+error[E0284]: type annotations needed: cannot satisfy `Foo == _`
+  --> $DIR/type-alias-impl-trait-tuple.rs:25:10
+   |
+LL |         (self.my_foo, self.my_u8, make_foo())
+   |          ^^^^^^^^^^^ cannot satisfy `Foo == _`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
index 1f2d0e47ea3..7bf899a96be 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
@@ -1,4 +1,6 @@
-// check-pass
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+//[current] check-pass
 
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
@@ -17,9 +19,11 @@ struct Blah {
 impl Blah {
     fn new() -> Blah {
         Blah { my_foo: make_foo(), my_u8: 12 }
+        //[next]~^ ERROR type annotations needed: cannot satisfy `Foo == _`
     }
     fn into_inner(self) -> (Foo, u8, Foo) {
         (self.my_foo, self.my_u8, make_foo())
+        //[next]~^ ERROR type annotations needed: cannot satisfy `Foo == _`
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
index 7d7cad874fa..22a3d7bd32f 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/type_of_a_let.rs:16:16
+  --> $DIR/type_of_a_let.rs:20:16
    |
 LL |     let x: Foo = 22_u32;
    |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
@@ -9,7 +9,7 @@ LL |     same_type((x, y));
    |                ^ value used here after move
 
 error[E0382]: use of moved value: `y`
-  --> $DIR/type_of_a_let.rs:17:6
+  --> $DIR/type_of_a_let.rs:21:6
    |
 LL |     let y: Foo = x;
    |         - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
index 36161171555..0f4dac6c683 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.rs
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
@@ -1,3 +1,7 @@
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+//[next] check-pass
+
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
@@ -13,8 +17,8 @@ fn foo1() -> (u32, Foo) {
 fn foo2() -> (u32, Foo) {
     let x: Foo = 22_u32;
     let y: Foo = x;
-    same_type((x, y)); //~ ERROR use of moved value
-    (y, todo!()) //~ ERROR use of moved value
+    same_type((x, y)); //[current]~ ERROR use of moved value
+    (y, todo!()) //[current]~ ERROR use of moved value
 }
 
 fn same_type<T>(x: (T, T)) {}