diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index 9fd7219499b27..d5d3f7767b133 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -100,7 +100,33 @@ impl Qualif for HasMutInterior {
     }
 
     fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        !ty.is_freeze(cx.tcx, cx.param_env)
+        // Avoid selecting for simple cases, such as builtin types.
+        if ty.is_trivially_freeze() {
+            return false;
+        }
+
+        // We do not use `ty.is_freeze` here, because that requires revealing opaque types, which
+        // requires borrowck, which in turn will invoke mir_const_qualifs again, causing a cycle error.
+        // Instead we invoke an obligation context manually, and provide the opaque type inference settings
+        // that allow the trait solver to just error out instead of cycling.
+        let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span));
+
+        let obligation = Obligation::new(
+            cx.tcx,
+            ObligationCause::dummy_with_span(cx.body.span),
+            cx.param_env,
+            ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
+        );
+
+        let infcx = cx
+            .tcx
+            .infer_ctxt()
+            .with_opaque_type_inference(cx.body.source.def_id().expect_local())
+            .build();
+        let ocx = ObligationCtxt::new(&infcx);
+        ocx.register_obligation(obligation);
+        let errors = ocx.select_all_or_error();
+        !errors.is_empty()
     }
 
     fn in_adt_inherently<'tcx>(
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 9307e38068128..4335d96737aaf 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1268,7 +1268,7 @@ impl<'tcx> Ty<'tcx> {
     ///
     /// Returning true means the type is known to be `Freeze`. Returning
     /// `false` means nothing -- could be `Freeze`, might not be.
-    fn is_trivially_freeze(self) -> bool {
+    pub fn is_trivially_freeze(self) -> bool {
         match self.kind() {
             ty::Int(_)
             | ty::Uint(_)
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 4c3d833b0f90f..06b79ea63ca47 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -772,7 +772,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     );
                 }
 
-                ty::Alias(ty::Opaque, _) => {
+                ty::Alias(ty::Opaque, alias) => {
                     if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
                         // We do not generate an auto impl candidate for `impl Trait`s which already
                         // reference our auto trait.
@@ -787,6 +787,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         // We do not emit auto trait candidates for opaque types in coherence.
                         // Doing so can result in weird dependency cycles.
                         candidates.ambiguous = true;
+                    } else if self.infcx.can_define_opaque_ty(alias.def_id) {
+                        // We do not emit auto trait candidates for opaque types in their defining scope, as
+                        // we need to know the hidden type first, which we can't reliably know within the defining
+                        // scope.
+                        candidates.ambiguous = true;
                     } else {
                         candidates.vec.push(AutoImplCandidate)
                     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 02ad361f9f59f..c007cd5314a86 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2386,13 +2386,17 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             }
 
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
-                // We can resolve the `impl Trait` to its concrete type,
-                // which enforces a DAG between the functions requiring
-                // the auto trait bounds in question.
-                match self.tcx().type_of_opaque(def_id) {
-                    Ok(ty) => t.rebind(vec![ty.instantiate(self.tcx(), args)]),
-                    Err(_) => {
-                        return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
+                if self.infcx.can_define_opaque_ty(def_id) {
+                    unreachable!()
+                } else {
+                    // We can resolve the `impl Trait` to its concrete type,
+                    // which enforces a DAG between the functions requiring
+                    // the auto trait bounds in question.
+                    match self.tcx().type_of_opaque(def_id) {
+                        Ok(ty) => t.rebind(vec![ty.instantiate(self.tcx(), args)]),
+                        Err(_) => {
+                            return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
+                        }
                     }
                 }
             }
diff --git a/tests/ui/const-generics/opaque_types.stderr b/tests/ui/const-generics/opaque_types.stderr
index 2c7384984c694..3947d645fcbe2 100644
--- a/tests/ui/const-generics/opaque_types.stderr
+++ b/tests/ui/const-generics/opaque_types.stderr
@@ -122,8 +122,6 @@ note: ...which requires const checking `main::{constant#0}`...
    |
 LL |     foo::<42>();
    |           ^^
-   = note: ...which requires computing whether `Foo` is freeze...
-   = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Freeze`...
    = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
 note: cycle used when computing type of `Foo::{opaque#0}`
   --> $DIR/opaque_types.rs:3:12
diff --git a/tests/ui/consts/const-fn-cycle.rs b/tests/ui/consts/const-fn-cycle.rs
index 5175296a53e5b..2879e3049c0d9 100644
--- a/tests/ui/consts/const-fn-cycle.rs
+++ b/tests/ui/consts/const-fn-cycle.rs
@@ -7,6 +7,8 @@
 /// to end up revealing opaque types (the RPIT in `many`'s return type),
 /// which can quickly lead to cycles.
 
+//@ check-pass
+
 pub struct Parser<H>(H);
 
 impl<H, T> Parser<H>
@@ -18,7 +20,6 @@ where
     }
 
     pub const fn many<'s>(&'s self) -> Parser<impl for<'a> Fn(&'a str) -> Vec<T> + 's> {
-        //~^ ERROR: cycle detected
         Parser::new(|_| unimplemented!())
     }
 }
diff --git a/tests/ui/consts/const-fn-cycle.stderr b/tests/ui/consts/const-fn-cycle.stderr
deleted file mode 100644
index c851f7342be9c..0000000000000
--- a/tests/ui/consts/const-fn-cycle.stderr
+++ /dev/null
@@ -1,34 +0,0 @@
-error[E0391]: cycle detected when computing type of opaque `<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many::{opaque#0}`
-  --> $DIR/const-fn-cycle.rs:20:47
-   |
-LL |     pub const fn many<'s>(&'s self) -> Parser<impl for<'a> Fn(&'a str) -> Vec<T> + 's> {
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many`...
-  --> $DIR/const-fn-cycle.rs:20:5
-   |
-LL |     pub const fn many<'s>(&'s self) -> Parser<impl for<'a> Fn(&'a str) -> Vec<T> + 's> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many`...
-  --> $DIR/const-fn-cycle.rs:20:5
-   |
-LL |     pub const fn many<'s>(&'s self) -> Parser<impl for<'a> Fn(&'a str) -> Vec<T> + 's> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const checking `<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many`...
-  --> $DIR/const-fn-cycle.rs:20:5
-   |
-LL |     pub const fn many<'s>(&'s self) -> Parser<impl for<'a> Fn(&'a str) -> Vec<T> + 's> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `Parser<<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many::{opaque#0}>` is freeze...
-   = note: ...which requires evaluating trait selection obligation `Parser<<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many::{opaque#0}>: core::marker::Freeze`...
-   = note: ...which again requires computing type of opaque `<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `<impl at $DIR/const-fn-cycle.rs:12:1: 14:33>::many::{opaque#0}`
-  --> $DIR/const-fn-cycle.rs:20:47
-   |
-LL |     pub const fn many<'s>(&'s self) -> Parser<impl for<'a> Fn(&'a str) -> Vec<T> + 's> {
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/consts/const-promoted-opaque.atomic.stderr b/tests/ui/consts/const-promoted-opaque.atomic.stderr
index a0459f4040ec6..1f2a7753ff543 100644
--- a/tests/ui/consts/const-promoted-opaque.atomic.stderr
+++ b/tests/ui/consts/const-promoted-opaque.atomic.stderr
@@ -1,5 +1,5 @@
 error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
-  --> $DIR/const-promoted-opaque.rs:29:25
+  --> $DIR/const-promoted-opaque.rs:28:25
    |
 LL |     let _: &'static _ = &FOO;
    |                         ^^^^
@@ -9,7 +9,7 @@ LL |     let _: &'static _ = &FOO;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time
-  --> $DIR/const-promoted-opaque.rs:29:26
+  --> $DIR/const-promoted-opaque.rs:28:26
    |
 LL |     let _: &'static _ = &FOO;
    |                          ^^^ the destructor for this type cannot be evaluated in constants
@@ -18,13 +18,13 @@ LL | };
    | - value is dropped here
 
 error[E0492]: constants cannot refer to interior mutable data
-  --> $DIR/const-promoted-opaque.rs:34:19
+  --> $DIR/const-promoted-opaque.rs:33:19
    |
 LL | const BAZ: &Foo = &FOO;
    |                   ^^^^ this borrow of an interior mutable value may end up in the final value
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-promoted-opaque.rs:38:26
+  --> $DIR/const-promoted-opaque.rs:37:26
    |
 LL |     let _: &'static _ = &FOO;
    |            ----------    ^^^ creates a temporary value which is freed while still in use
@@ -34,38 +34,7 @@ LL |
 LL | }
    | - temporary value is freed at the end of this statement
 
-error[E0391]: cycle detected when computing type of opaque `helper::Foo::{opaque#0}`
-  --> $DIR/const-promoted-opaque.rs:14:20
-   |
-LL |     pub type Foo = impl Sized;
-   |                    ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `helper::FOO`...
-  --> $DIR/const-promoted-opaque.rs:21:5
-   |
-LL |     pub const FOO: Foo = std::sync::atomic::AtomicU8::new(42);
-   |     ^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `helper::FOO`...
-  --> $DIR/const-promoted-opaque.rs:21:5
-   |
-LL |     pub const FOO: Foo = std::sync::atomic::AtomicU8::new(42);
-   |     ^^^^^^^^^^^^^^^^^^
-note: ...which requires const checking `helper::FOO`...
-  --> $DIR/const-promoted-opaque.rs:21:5
-   |
-LL |     pub const FOO: Foo = std::sync::atomic::AtomicU8::new(42);
-   |     ^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `helper::Foo` is freeze...
-   = note: ...which requires evaluating trait selection obligation `helper::Foo: core::marker::Freeze`...
-   = note: ...which again requires computing type of opaque `helper::Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `helper::Foo::{opaque#0}`
-  --> $DIR/const-promoted-opaque.rs:14:20
-   |
-LL |     pub type Foo = impl Sized;
-   |                    ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0391, E0492, E0493, E0658, E0716.
-For more information about an error, try `rustc --explain E0391`.
+Some errors have detailed explanations: E0492, E0493, E0658, E0716.
+For more information about an error, try `rustc --explain E0492`.
diff --git a/tests/ui/consts/const-promoted-opaque.rs b/tests/ui/consts/const-promoted-opaque.rs
index e20823527f48b..303618df9df06 100644
--- a/tests/ui/consts/const-promoted-opaque.rs
+++ b/tests/ui/consts/const-promoted-opaque.rs
@@ -12,7 +12,6 @@
 
 mod helper {
     pub type Foo = impl Sized;
-    //[string,atomic]~^ ERROR cycle detected
 
     #[cfg(string)]
     pub const FOO: Foo = String::new();
@@ -28,11 +27,11 @@ use helper::*;
 const BAR: () = {
     let _: &'static _ = &FOO;
     //[string,atomic]~^ ERROR: destructor of `helper::Foo` cannot be evaluated at compile-time
-    //[string,atomic]~| ERROR: cannot borrow here
+    //[atomic]~| ERROR: cannot borrow here
 };
 
 const BAZ: &Foo = &FOO;
-//[string,atomic]~^ ERROR: constants cannot refer to interior mutable data
+//[atomic]~^ ERROR: constants cannot refer to interior mutable data
 
 fn main() {
     let _: &'static _ = &FOO;
diff --git a/tests/ui/consts/const-promoted-opaque.string.stderr b/tests/ui/consts/const-promoted-opaque.string.stderr
index a613d517e68ef..fa1dbb05d175d 100644
--- a/tests/ui/consts/const-promoted-opaque.string.stderr
+++ b/tests/ui/consts/const-promoted-opaque.string.stderr
@@ -1,15 +1,5 @@
-error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
-  --> $DIR/const-promoted-opaque.rs:29:25
-   |
-LL |     let _: &'static _ = &FOO;
-   |                         ^^^^
-   |
-   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
-   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time
-  --> $DIR/const-promoted-opaque.rs:29:26
+  --> $DIR/const-promoted-opaque.rs:28:26
    |
 LL |     let _: &'static _ = &FOO;
    |                          ^^^ the destructor for this type cannot be evaluated in constants
@@ -17,14 +7,8 @@ LL |     let _: &'static _ = &FOO;
 LL | };
    | - value is dropped here
 
-error[E0492]: constants cannot refer to interior mutable data
-  --> $DIR/const-promoted-opaque.rs:34:19
-   |
-LL | const BAZ: &Foo = &FOO;
-   |                   ^^^^ this borrow of an interior mutable value may end up in the final value
-
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-promoted-opaque.rs:38:26
+  --> $DIR/const-promoted-opaque.rs:37:26
    |
 LL |     let _: &'static _ = &FOO;
    |            ----------    ^^^ creates a temporary value which is freed while still in use
@@ -34,38 +18,7 @@ LL |
 LL | }
    | - temporary value is freed at the end of this statement
 
-error[E0391]: cycle detected when computing type of opaque `helper::Foo::{opaque#0}`
-  --> $DIR/const-promoted-opaque.rs:14:20
-   |
-LL |     pub type Foo = impl Sized;
-   |                    ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `helper::FOO`...
-  --> $DIR/const-promoted-opaque.rs:18:5
-   |
-LL |     pub const FOO: Foo = String::new();
-   |     ^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `helper::FOO`...
-  --> $DIR/const-promoted-opaque.rs:18:5
-   |
-LL |     pub const FOO: Foo = String::new();
-   |     ^^^^^^^^^^^^^^^^^^
-note: ...which requires const checking `helper::FOO`...
-  --> $DIR/const-promoted-opaque.rs:18:5
-   |
-LL |     pub const FOO: Foo = String::new();
-   |     ^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `helper::Foo` is freeze...
-   = note: ...which requires evaluating trait selection obligation `helper::Foo: core::marker::Freeze`...
-   = note: ...which again requires computing type of opaque `helper::Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `helper::Foo::{opaque#0}`
-  --> $DIR/const-promoted-opaque.rs:14:20
-   |
-LL |     pub type Foo = impl Sized;
-   |                    ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0391, E0492, E0493, E0658, E0716.
-For more information about an error, try `rustc --explain E0391`.
+Some errors have detailed explanations: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
new file mode 100644
index 0000000000000..5caf0eb2fd4e3
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
@@ -0,0 +1,22 @@
+error[E0283]: type annotations needed
+  --> $DIR/auto-trait-selection-freeze.rs:19:16
+   |
+LL |     if false { is_trait(foo()) } else { Default::default() }
+   |                ^^^^^^^^ ----- type must be known at this point
+   |                |
+   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
+   |
+   = note: cannot satisfy `_: Trait<_>`
+note: required by a bound in `is_trait`
+  --> $DIR/auto-trait-selection-freeze.rs:11:16
+   |
+LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+   |                ^^^^^^^^ required by this bound in `is_trait`
+help: consider specifying the generic arguments
+   |
+LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
+   |                        ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr
new file mode 100644
index 0000000000000..b4d2229d408d2
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr
@@ -0,0 +1,26 @@
+error[E0283]: type annotations needed
+  --> $DIR/auto-trait-selection-freeze.rs:19:16
+   |
+LL |     if false { is_trait(foo()) } else { Default::default() }
+   |                ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait`
+   |
+note: multiple `impl`s satisfying `impl Sized: Trait<_>` found
+  --> $DIR/auto-trait-selection-freeze.rs:16:1
+   |
+LL | impl<T: Freeze> Trait<u32> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<T> Trait<i32> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `is_trait`
+  --> $DIR/auto-trait-selection-freeze.rs:11:16
+   |
+LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+   |                ^^^^^^^^ required by this bound in `is_trait`
+help: consider specifying the generic arguments
+   |
+LL |     if false { is_trait::<_, U>(foo()) } else { Default::default() }
+   |                        ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.rs b/tests/ui/impl-trait/auto-trait-selection-freeze.rs
new file mode 100644
index 0000000000000..7306a1c41f746
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.rs
@@ -0,0 +1,23 @@
+//! This test shows how we fail selection in a way that can influence
+//! selection in a code path that succeeds.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+
+#![feature(freeze)]
+
+use std::marker::Freeze;
+
+fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+    Default::default()
+}
+
+trait Trait<T> {}
+impl<T: Freeze> Trait<u32> for T {}
+impl<T> Trait<i32> for T {}
+fn foo() -> impl Sized {
+    if false { is_trait(foo()) } else { Default::default() }
+    //~^ ERROR: type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr
new file mode 100644
index 0000000000000..d34fdcc44967f
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr
@@ -0,0 +1,22 @@
+error[E0283]: type annotations needed
+  --> $DIR/auto-trait-selection.rs:15:16
+   |
+LL |     if false { is_trait(foo()) } else { Default::default() }
+   |                ^^^^^^^^ ----- type must be known at this point
+   |                |
+   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
+   |
+   = note: cannot satisfy `_: Trait<_>`
+note: required by a bound in `is_trait`
+  --> $DIR/auto-trait-selection.rs:7:16
+   |
+LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+   |                ^^^^^^^^ required by this bound in `is_trait`
+help: consider specifying the generic arguments
+   |
+LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
+   |                        ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.old.stderr b/tests/ui/impl-trait/auto-trait-selection.old.stderr
new file mode 100644
index 0000000000000..1b5fd95fdf903
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-selection.old.stderr
@@ -0,0 +1,26 @@
+error[E0283]: type annotations needed
+  --> $DIR/auto-trait-selection.rs:15:16
+   |
+LL |     if false { is_trait(foo()) } else { Default::default() }
+   |                ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait`
+   |
+note: multiple `impl`s satisfying `impl Sized: Trait<_>` found
+  --> $DIR/auto-trait-selection.rs:12:1
+   |
+LL | impl<T: Send> Trait<u32> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<T> Trait<i32> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `is_trait`
+  --> $DIR/auto-trait-selection.rs:7:16
+   |
+LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+   |                ^^^^^^^^ required by this bound in `is_trait`
+help: consider specifying the generic arguments
+   |
+LL |     if false { is_trait::<_, U>(foo()) } else { Default::default() }
+   |                        ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.rs b/tests/ui/impl-trait/auto-trait-selection.rs
new file mode 100644
index 0000000000000..ee5612459c257
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-selection.rs
@@ -0,0 +1,19 @@
+//! This test shows how we fail selection in a way that can influence
+//! selection in a code path that succeeds.
+
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
+
+fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
+    Default::default()
+}
+
+trait Trait<T> {}
+impl<T: Send> Trait<u32> for T {}
+impl<T> Trait<i32> for T {}
+fn foo() -> impl Sized {
+    if false { is_trait(foo()) } else { Default::default() }
+    //~^ ERROR: type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
index fe6e166cb4fa1..fb51bb7b4173b 100644
--- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope
-  --> $DIR/call_method_on_inherent_impl_ref.rs:20:11
+  --> $DIR/call_method_on_inherent_impl_ref.rs:19:11
    |
 LL |     fn my_debug(&self);
    |        -------- the method is available for `&impl Debug` here
@@ -14,27 +14,6 @@ note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
 LL | trait MyDebug {
    | ^^^^^^^^^^^^^
 
-error[E0391]: cycle detected when computing type of opaque `my_foo::{opaque#0}`
-  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
-   |
-LL | fn my_foo() -> impl std::fmt::Debug {
-   |                ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `my_foo`...
-  --> $DIR/call_method_on_inherent_impl_ref.rs:20:9
-   |
-LL |         x.my_debug();
-   |         ^
-   = note: ...which requires evaluating trait selection obligation `my_foo::{opaque#0}: core::marker::Unpin`...
-   = note: ...which again requires computing type of opaque `my_foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `my_foo::{opaque#0}`
-  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
-   |
-LL | fn my_foo() -> impl std::fmt::Debug {
-   |                ^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0391, E0599.
-For more information about an error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
index 327f6ca3450f1..7202cb6f90a6f 100644
--- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/call_method_on_inherent_impl_ref.rs:18:13
+  --> $DIR/call_method_on_inherent_impl_ref.rs:17:13
    |
 LL |         let x = my_foo();
    |             ^
@@ -13,7 +13,7 @@ LL |         let x: /* Type */ = my_foo();
    |              ++++++++++++
 
 error[E0282]: type annotations needed for `&_`
-  --> $DIR/call_method_on_inherent_impl_ref.rs:28:13
+  --> $DIR/call_method_on_inherent_impl_ref.rs:27:13
    |
 LL |         let x = &my_bar();
    |             ^
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
index 40ad21532a4e2..abe60e5e45a34 100644
--- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
@@ -13,7 +13,6 @@ where
 }
 
 fn my_foo() -> impl std::fmt::Debug {
-    //[current]~^ cycle
     if false {
         let x = my_foo();
         //[next]~^ type annotations needed
diff --git a/tests/ui/impl-trait/rpit/const_check_false_cycle.rs b/tests/ui/impl-trait/rpit/const_check_false_cycle.rs
new file mode 100644
index 0000000000000..d4ea0e3b14785
--- /dev/null
+++ b/tests/ui/impl-trait/rpit/const_check_false_cycle.rs
@@ -0,0 +1,14 @@
+//! This test caused a cycle error when checking whether the
+//! return type is `Freeze` during const checking, even though
+//! the information is readily available.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+const fn f() -> impl Eq {
+    g()
+}
+const fn g() {}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr
index bab8d1cd83b30..586ae07602821 100644
--- a/tests/ui/impl-trait/unsized_coercion3.next.stderr
+++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr
@@ -5,7 +5,7 @@ LL |         let x = hello();
    |                 ^^^^^^^ types differ
 
 error[E0308]: mismatched types
-  --> $DIR/unsized_coercion3.rs:19:14
+  --> $DIR/unsized_coercion3.rs:18:14
    |
 LL | fn hello() -> Box<impl Trait + ?Sized> {
    |                   ------------------- the expected opaque type
@@ -21,7 +21,7 @@ note: associated function defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
 
 error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
-  --> $DIR/unsized_coercion3.rs:19:14
+  --> $DIR/unsized_coercion3.rs:18:14
    |
 LL |     Box::new(1u32)
    |     -------- ^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/impl-trait/unsized_coercion3.old.stderr b/tests/ui/impl-trait/unsized_coercion3.old.stderr
index 24a302d7007ab..52a72b84a8dd6 100644
--- a/tests/ui/impl-trait/unsized_coercion3.old.stderr
+++ b/tests/ui/impl-trait/unsized_coercion3.old.stderr
@@ -1,17 +1,3 @@
-error: cannot check whether the hidden type of opaque type satisfies auto traits
-  --> $DIR/unsized_coercion3.rs:15:32
-   |
-LL |         let y: Box<dyn Send> = x;
-   |                                ^
-   |
-   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-note: opaque type is declared here
-  --> $DIR/unsized_coercion3.rs:11:19
-   |
-LL | fn hello() -> Box<impl Trait + ?Sized> {
-   |                   ^^^^^^^^^^^^^^^^^^^
-   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`
-
 error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
   --> $DIR/unsized_coercion3.rs:15:32
    |
@@ -21,6 +7,6 @@ LL |         let y: Box<dyn Send> = x;
    = help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
    = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion3.rs b/tests/ui/impl-trait/unsized_coercion3.rs
index 85950ac583ebc..7e862de2157d9 100644
--- a/tests/ui/impl-trait/unsized_coercion3.rs
+++ b/tests/ui/impl-trait/unsized_coercion3.rs
@@ -14,7 +14,6 @@ fn hello() -> Box<impl Trait + ?Sized> {
         //[next]~^ ERROR: type mismatch resolving `impl Trait + ?Sized <: dyn Send`
         let y: Box<dyn Send> = x;
         //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
-        //[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
     }
     Box::new(1u32)
     //[next]~^ ERROR: mismatched types
diff --git a/tests/ui/impl-trait/unsized_coercion5.old.stderr b/tests/ui/impl-trait/unsized_coercion5.old.stderr
index b6437266f27dd..06ad54b1f1d8b 100644
--- a/tests/ui/impl-trait/unsized_coercion5.old.stderr
+++ b/tests/ui/impl-trait/unsized_coercion5.old.stderr
@@ -9,20 +9,6 @@ LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
    = note: expected struct `Box<dyn Send>`
               found struct `Box<dyn Trait + Send>`
 
-error: cannot check whether the hidden type of opaque type satisfies auto traits
-  --> $DIR/unsized_coercion5.rs:16:32
-   |
-LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
-   |                                ^
-   |
-   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-note: opaque type is declared here
-  --> $DIR/unsized_coercion5.rs:13:19
-   |
-LL | fn hello() -> Box<impl Trait + ?Sized> {
-   |                   ^^^^^^^^^^^^^^^^^^^
-   = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
-
 error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
   --> $DIR/unsized_coercion5.rs:16:32
    |
@@ -32,7 +18,7 @@ LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
    = help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
    = note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion5.rs b/tests/ui/impl-trait/unsized_coercion5.rs
index b007267a0066f..85d313caa1355 100644
--- a/tests/ui/impl-trait/unsized_coercion5.rs
+++ b/tests/ui/impl-trait/unsized_coercion5.rs
@@ -15,8 +15,7 @@ fn hello() -> Box<impl Trait + ?Sized> {
         let x = hello();
         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
         //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
-        //[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
-        //~^^^ ERROR: mismatched types
+        //~^^ ERROR: mismatched types
     }
     Box::new(1u32)
 }
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs
index ab46d49073c7a..9cd18d4566da1 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.rs
@@ -9,7 +9,6 @@ impl MyTrait for i32 {
         //~| ERROR functions in trait impls cannot be declared const
         //~| ERROR functions cannot be both `const` and `async`
         //~| ERROR method `bar` is not a member
-        //~| ERROR cycle detected when computing type
         main8().await;
         //~^ ERROR cannot find function
     }
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr
index 1f309e1e85446..90771c344b51d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/ice-120503-async-const-method.stderr
@@ -61,7 +61,7 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
    = help: use `-Znext-solver` to enable
 
 error[E0425]: cannot find function `main8` in this scope
-  --> $DIR/ice-120503-async-const-method.rs:13:9
+  --> $DIR/ice-120503-async-const-method.rs:12:9
    |
 LL |         main8().await;
    |         ^^^^^ help: a function with a similar name exists: `main`
@@ -69,38 +69,7 @@ LL |         main8().await;
 LL | fn main() {}
    | --------- similarly named function `main` defined here
 
-error[E0391]: cycle detected when computing type of opaque `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}`
-  --> $DIR/ice-120503-async-const-method.rs:7:5
-   |
-LL |     async const fn bar(&self) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar`...
-  --> $DIR/ice-120503-async-const-method.rs:7:5
-   |
-LL |     async const fn bar(&self) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar`...
-  --> $DIR/ice-120503-async-const-method.rs:7:5
-   |
-LL |     async const fn bar(&self) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const checking `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar`...
-  --> $DIR/ice-120503-async-const-method.rs:7:5
-   |
-LL |     async const fn bar(&self) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}` is freeze...
-   = note: ...which requires evaluating trait selection obligation `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}: core::marker::Freeze`...
-   = note: ...which again requires computing type of opaque `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `<impl at $DIR/ice-120503-async-const-method.rs:6:1: 6:21>::bar::{opaque#0}`
-  --> $DIR/ice-120503-async-const-method.rs:7:5
-   |
-LL |     async const fn bar(&self) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 7 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0379, E0391, E0407, E0425.
+Some errors have detailed explanations: E0379, E0407, E0425.
 For more information about an error, try `rustc --explain E0379`.
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs
index 7c0de39c7c91c..a089fdc907531 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.rs
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs
@@ -4,13 +4,13 @@
 #![feature(type_alias_impl_trait)]
 type Bar = impl Sized;
 //~^ ERROR: cycle
-//~| ERROR: cycle
 
 fn foo() -> Bar
 where
     Bar: Send,
 {
     [0; 1 + 2]
+    //~^ ERROR: type annotations needed: cannot satisfy `Bar: Send`
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr
index 9c08b8f127d27..f1361b47c56e6 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr
@@ -10,7 +10,7 @@ note: ...which requires computing type of opaque `Bar::{opaque#0}`...
 LL | type Bar = impl Sized;
    |            ^^^^^^^^^^
 note: ...which requires type-checking `foo`...
-  --> $DIR/in-where-clause.rs:9:1
+  --> $DIR/in-where-clause.rs:8:1
    |
 LL | / fn foo() -> Bar
 LL | | where
@@ -25,26 +25,23 @@ LL | type Bar = impl Sized;
    |            ^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
-  --> $DIR/in-where-clause.rs:5:12
-   |
-LL | type Bar = impl Sized;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `foo`...
-  --> $DIR/in-where-clause.rs:13:9
+error[E0283]: type annotations needed: cannot satisfy `Bar: Send`
+  --> $DIR/in-where-clause.rs:12:9
    |
 LL |     [0; 1 + 2]
    |         ^^^^^
-   = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`...
-   = note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `Bar::{opaque#0}`
-  --> $DIR/in-where-clause.rs:5:12
    |
-LL | type Bar = impl Sized;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+   = note: cannot satisfy `Bar: Send`
+note: required by a bound in `foo`
+  --> $DIR/in-where-clause.rs:10:10
+   |
+LL | fn foo() -> Bar
+   |    --- required by a bound in this function
+LL | where
+LL |     Bar: Send,
+   |          ^^^^ required by this bound in `foo`
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0391`.
+Some errors have detailed explanations: E0283, E0391.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs
index 07fd989b0fa78..34f3788e2341b 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.rs
+++ b/tests/ui/type-alias-impl-trait/reveal_local.rs
@@ -20,7 +20,7 @@ fn not_gooder() -> Foo {
     // while we could know this from the hidden type, it would
     // need extra roundabout logic to support it.
     is_send::<Foo>();
-    //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
+    //~^ ERROR: type annotations needed: cannot satisfy `Foo: Send`
 
     x
 }
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr
index e1b320cc38e31..9829c58cf73b7 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr
@@ -16,18 +16,13 @@ note: required by a bound in `is_send`
 LL | fn is_send<T: Send>() {}
    |               ^^^^ required by this bound in `is_send`
 
-error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
+error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
   --> $DIR/reveal_local.rs:22:15
    |
 LL |     is_send::<Foo>();
    |               ^^^
    |
-   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-note: opaque type is declared here
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
+   = note: cannot satisfy `Foo: Send`
 note: required by a bound in `is_send`
   --> $DIR/reveal_local.rs:7:15
    |
@@ -36,3 +31,4 @@ LL | fn is_send<T: Send>() {}
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0283`.