about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs106
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs10
-rw-r--r--compiler/rustc_infer/src/infer/relate/equate.rs35
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.rs4
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.stderr22
-rw-r--r--tests/ui/closure-expected-type/expect-fn-supply-fn.rs6
-rw-r--r--tests/ui/closure-expected-type/expect-fn-supply-fn.stderr24
-rw-r--r--tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs20
-rw-r--r--tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr10
-rw-r--r--tests/ui/coherence/coherence-fn-inputs.rs12
-rw-r--r--tests/ui/coherence/coherence-fn-inputs.stderr10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr18
-rw-r--r--tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs38
-rw-r--r--tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr22
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs24
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr11
-rw-r--r--tests/ui/lub-glb/old-lub-glb-hr-eq.rs3
-rw-r--r--tests/ui/lub-glb/old-lub-glb-hr-eq.stderr19
-rw-r--r--tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs5
-rw-r--r--tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr22
-rw-r--r--tests/ui/traits/next-solver/member-constraints-in-root-universe.rs2
-rw-r--r--tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr8
22 files changed, 319 insertions, 112 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 00296aa38da..85f63371659 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -483,61 +483,59 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
             return Ok(ty::Binder::dummy(a));
         }
 
-        if self.ambient_covariance() {
-            // Covariance, so we want `for<..> A <: for<..> B` --
-            // therefore we compare any instantiation of A (i.e., A
-            // instantiated with existentials) against every
-            // instantiation of B (i.e., B instantiated with
-            // universals).
-
-            // Reset the ambient variance to covariant. This is needed
-            // to correctly handle cases like
-            //
-            //     for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32)
-            //
-            // Somewhat surprisingly, these two types are actually
-            // **equal**, even though the one on the right looks more
-            // polymorphic. The reason is due to subtyping. To see it,
-            // consider that each function can call the other:
-            //
-            // - The left function can call the right with `'b` and
-            //   `'c` both equal to `'a`
-            //
-            // - The right function can call the left with `'a` set to
-            //   `{P}`, where P is the point in the CFG where the call
-            //   itself occurs. Note that `'b` and `'c` must both
-            //   include P. At the point, the call works because of
-            //   subtyping (i.e., `&'b u32 <: &{P} u32`).
-            let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant);
-
-            // Note: the order here is important. Create the placeholders first, otherwise
-            // we assign the wrong universe to the existential!
-            self.enter_forall(b, |this, b| {
-                let a = this.instantiate_binder_with_existentials(a);
-                this.relate(a, b)
-            })?;
-
-            self.ambient_variance = variance;
-        }
+        match self.ambient_variance {
+            ty::Variance::Covariant => {
+                // Covariance, so we want `for<..> A <: for<..> B` --
+                // therefore we compare any instantiation of A (i.e., A
+                // instantiated with existentials) against every
+                // instantiation of B (i.e., B instantiated with
+                // universals).
+
+                // Note: the order here is important. Create the placeholders first, otherwise
+                // we assign the wrong universe to the existential!
+                self.enter_forall(b, |this, b| {
+                    let a = this.instantiate_binder_with_existentials(a);
+                    this.relate(a, b)
+                })?;
+            }
 
-        if self.ambient_contravariance() {
-            // Contravariance, so we want `for<..> A :> for<..> B`
-            // -- therefore we compare every instantiation of A (i.e.,
-            // A instantiated with universals) against any
-            // instantiation of B (i.e., B instantiated with
-            // existentials). Opposite of above.
-
-            // Reset ambient variance to contravariance. See the
-            // covariant case above for an explanation.
-            let variance =
-                std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant);
-
-            self.enter_forall(a, |this, a| {
-                let b = this.instantiate_binder_with_existentials(b);
-                this.relate(a, b)
-            })?;
-
-            self.ambient_variance = variance;
+            ty::Variance::Contravariant => {
+                // Contravariance, so we want `for<..> A :> for<..> B` --
+                // therefore we compare every instantiation of A (i.e., A
+                // instantiated with universals) against any
+                // instantiation of B (i.e., B instantiated with
+                // existentials). Opposite of above.
+
+                // Note: the order here is important. Create the placeholders first, otherwise
+                // we assign the wrong universe to the existential!
+                self.enter_forall(a, |this, a| {
+                    let b = this.instantiate_binder_with_existentials(b);
+                    this.relate(a, b)
+                })?;
+            }
+
+            ty::Variance::Invariant => {
+                // Invariant, so we want `for<..> A == for<..> B` --
+                // therefore we want `exists<..> A == for<..> B` and
+                // `exists<..> B == for<..> A`.
+                //
+                // See the comment in `fn Equate::binders` for more details.
+
+                // Note: the order here is important. Create the placeholders first, otherwise
+                // we assign the wrong universe to the existential!
+                self.enter_forall(b, |this, b| {
+                    let a = this.instantiate_binder_with_existentials(a);
+                    this.relate(a, b)
+                })?;
+                // Note: the order here is important. Create the placeholders first, otherwise
+                // we assign the wrong universe to the existential!
+                self.enter_forall(a, |this, a| {
+                    let b = this.instantiate_binder_with_existentials(b);
+                    this.relate(a, b)
+                })?;
+            }
+
+            ty::Variance::Bivariant => {}
         }
 
         Ok(a)
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 3b7a7817279..6e9b4236e20 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -169,6 +169,7 @@ pub fn check_intrinsic_type(
 
     let bound_vars = tcx.mk_bound_variable_kinds(&[
         ty::BoundVariableKind::Region(ty::BrAnon),
+        ty::BoundVariableKind::Region(ty::BrAnon),
         ty::BoundVariableKind::Region(ty::BrEnv),
     ]);
     let mk_va_list_ty = |mutbl| {
@@ -181,7 +182,7 @@ pub fn check_intrinsic_type(
             let env_region = ty::Region::new_bound(
                 tcx,
                 ty::INNERMOST,
-                ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
+                ty::BoundRegion { var: ty::BoundVar::from_u32(2), kind: ty::BrEnv },
             );
             let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
             (Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
@@ -493,9 +494,12 @@ pub fn check_intrinsic_type(
 
             sym::raw_eq => {
                 let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon };
-                let param_ty =
+                let param_ty_lhs =
+                    Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
+                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon };
+                let param_ty_rhs =
                     Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
-                (1, 0, vec![param_ty; 2], tcx.types.bool)
+                (1, 0, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool)
             }
 
             sym::black_box => (1, 0, vec![param(0)], param(0)),
diff --git a/compiler/rustc_infer/src/infer/relate/equate.rs b/compiler/rustc_infer/src/infer/relate/equate.rs
index 43d6aef3e15..1617a062ea0 100644
--- a/compiler/rustc_infer/src/infer/relate/equate.rs
+++ b/compiler/rustc_infer/src/infer/relate/equate.rs
@@ -1,12 +1,13 @@
 use super::combine::{CombineFields, ObligationEmittingRelation};
 use super::StructurallyRelateAliases;
+use crate::infer::BoundRegionConversionTime::HigherRankedType;
 use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
 use crate::traits::PredicateObligations;
 
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use rustc_hir::def_id::DefId;
 use rustc_span::Span;
@@ -167,12 +168,34 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
             return Ok(a);
         }
 
-        if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
-            self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
-            self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
-        } else {
+        if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) {
             // Fast path for the common case.
-            self.relate(a.skip_binder(), b.skip_binder())?;
+            self.relate(a, b)?;
+        } else {
+            // When equating binders, we check that there is a 1-to-1
+            // correspondence between the bound vars in both types.
+            //
+            // We do so by separately instantiating one of the binders with
+            // placeholders and the other with inference variables and then
+            // equating the instantiated types.
+            //
+            // We want `for<..> A == for<..> B` -- therefore we want
+            // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
+
+            let span = self.fields.trace.cause.span;
+            let infcx = self.fields.infcx;
+
+            // Check if `exists<..> A == for<..> B`
+            infcx.enter_forall(b, |b| {
+                let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
+                self.relate(a, b)
+            })?;
+
+            // Check if `exists<..> B == for<..> A`.
+            infcx.enter_forall(a, |a| {
+                let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
+                self.relate(a, b)
+            })?;
         }
         Ok(a)
     }
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs
index dd62e59f07d..3255bf20ebd 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.rs
+++ b/tests/ui/associated-inherent-types/issue-111404-1.rs
@@ -8,7 +8,9 @@ impl<'a> Foo<fn(&'a ())> {
 }
 
 fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
-//~^ ERROR higher-ranked subtype error
+//~^ ERROR mismatched types [E0308]
+//~| ERROR mismatched types [E0308]
+//~| ERROR higher-ranked subtype error
 //~| ERROR higher-ranked subtype error
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr
index cf4d4a5f19b..5074c877a8e 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr
@@ -1,3 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-111404-1.rs:10:11
+   |
+LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected struct `Foo<fn(&())>`
+              found struct `Foo<for<'b> fn(&'b ())>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-111404-1.rs:10:11
+   |
+LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected struct `Foo<fn(&())>`
+              found struct `Foo<for<'b> fn(&'b ())>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: higher-ranked subtype error
   --> $DIR/issue-111404-1.rs:10:1
    |
@@ -12,5 +31,6 @@ LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.rs b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs
index 7f1c140279c..7599d078351 100644
--- a/tests/ui/closure-expected-type/expect-fn-supply-fn.rs
+++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs
@@ -30,14 +30,16 @@ fn expect_free_supply_bound() {
     // Here, we are given a function whose region is bound at closure level,
     // but we expect one bound in the argument. Error results.
     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
-    //~^ ERROR mismatched types
+    //~^ ERROR mismatched types [E0308]
+    //~| ERROR lifetime may not live long enough
 }
 
 fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
     // Here, we are given a `fn(&u32)` but we expect a `fn(&'x
     // u32)`. In principle, this could be ok, but we demand equality.
     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
-    //~^ ERROR mismatched types
+    //~^ ERROR mismatched types [E0308]
+    //~| ERROR lifetime may not live long enough
 }
 
 fn expect_bound_supply_free_from_closure() {
diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
index e010f0502f8..4215cd0bc11 100644
--- a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
+++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -19,6 +19,15 @@ LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
 LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
    |                                                 ^ requires that `'x` must outlive `'static`
 
+error: lifetime may not live long enough
+  --> $DIR/expect-fn-supply-fn.rs:32:49
+   |
+LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+   |                                                 ^
+   |                                                 |
+   |                                                 has type `fn(&'1 u32)`
+   |                                                 requires that `'1` must outlive `'static`
+
 error[E0308]: mismatched types
   --> $DIR/expect-fn-supply-fn.rs:32:49
    |
@@ -29,7 +38,7 @@ LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
               found fn pointer `for<'a> fn(&'a _)`
 
 error[E0308]: mismatched types
-  --> $DIR/expect-fn-supply-fn.rs:39:50
+  --> $DIR/expect-fn-supply-fn.rs:40:50
    |
 LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
    |                                                  ^ one type is more general than the other
@@ -37,8 +46,17 @@ LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
    = note: expected fn pointer `for<'a> fn(&'a _)`
               found fn pointer `fn(&_)`
 
+error: lifetime may not live long enough
+  --> $DIR/expect-fn-supply-fn.rs:40:50
+   |
+LL | fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
+   |                                     -- lifetime `'x` defined here
+...
+LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+   |                                                  ^ requires that `'x` must outlive `'static`
+
 error[E0308]: mismatched types
-  --> $DIR/expect-fn-supply-fn.rs:48:50
+  --> $DIR/expect-fn-supply-fn.rs:50:50
    |
 LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
    |                                                  ^ one type is more general than the other
@@ -46,6 +64,6 @@ LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
    = note: expected fn pointer `for<'a> fn(&'a _)`
               found fn pointer `fn(&_)`
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs
index 99f805f7f0f..fb706ba1352 100644
--- a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs
+++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs
@@ -1,10 +1,15 @@
-// Test that impls for these two types are considered ovelapping:
+//@ check-pass
+
+// These types were previously considered equal as they are subtypes of each other.
+// This has been changed in #118247 and we now consider them to be disjoint.
+//
+// In our test:
 //
 // * `for<'r> fn(fn(&'r u32))`
 // * `fn(fn(&'a u32)` where `'a` is free
 //
-// This is because, for `'a = 'static`, the two types overlap.
-// Effectively for them to be equal to you get:
+// These were considered equal as for `'a = 'static` subtyping succeeds in both
+// directions:
 //
 // * `for<'r> fn(fn(&'r u32)) <: fn(fn(&'static u32))`
 //   * true if `exists<'r> { 'r: 'static }` (obviously true)
@@ -15,12 +20,7 @@ trait Trait {}
 
 impl Trait for for<'r> fn(fn(&'r ())) {}
 impl<'a> Trait for fn(fn(&'a ())) {}
-//~^ ERROR conflicting implementations
-//
-// Note in particular that we do NOT get a future-compatibility warning
-// here. This is because the new leak-check proposed in [MCP 295] does not
-// "error" when these two types are equated.
-//
-// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295
+//~^ WARN conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` [coherence_leak_check]
+//~| WARN the behavior may change in a future release
 
 fn main() {}
diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
index 316da26b54d..01694eaf5d1 100644
--- a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
+++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
@@ -1,13 +1,15 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
-  --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
+warning: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
+  --> $DIR/coherence-fn-covariant-bound-vs-static.rs:22:1
    |
 LL | impl Trait for for<'r> fn(fn(&'r ())) {}
    | ------------------------------------- first implementation here
 LL | impl<'a> Trait for fn(fn(&'a ())) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))`
    |
+   = warning: the behavior may change in a future release
+   = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+   = note: `#[warn(coherence_leak_check)]` on by default
 
-error: aborting due to 1 previous error
+warning: 1 warning emitted
 
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-fn-inputs.rs b/tests/ui/coherence/coherence-fn-inputs.rs
index 3afec5c5459..a88a846329d 100644
--- a/tests/ui/coherence/coherence-fn-inputs.rs
+++ b/tests/ui/coherence/coherence-fn-inputs.rs
@@ -1,11 +1,12 @@
-// Test that we consider these two types completely equal:
+//@ check-pass
+
+// These types were previously considered equal as they are subtypes of each other.
+// This has been changed in #118247 and we now consider them to be disjoint.
 //
 // * `for<'a, 'b> fn(&'a u32, &'b u32)`
 // * `for<'c> fn(&'c u32, &'c u32)`
 //
-// For a long time we considered these to be distinct types. But in fact they
-// are equivalent, if you work through the implications of subtyping -- this is
-// because:
+// These types are subtypes of each other as:
 //
 // * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection)
 // * `'a` and `'b` can both be equal to `'c`
@@ -13,7 +14,8 @@
 trait Trait {}
 impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
 impl Trait for for<'c> fn(&'c u32, &'c u32) {
-    //~^ ERROR conflicting implementations
+    //~^ WARN conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` [coherence_leak_check]
+    //~| WARN the behavior may change in a future release
     //
     // Note in particular that we do NOT get a future-compatibility warning
     // here. This is because the new leak-check proposed in [MCP 295] does not
diff --git a/tests/ui/coherence/coherence-fn-inputs.stderr b/tests/ui/coherence/coherence-fn-inputs.stderr
index 246ec5947b3..56f3a14833e 100644
--- a/tests/ui/coherence/coherence-fn-inputs.stderr
+++ b/tests/ui/coherence/coherence-fn-inputs.stderr
@@ -1,13 +1,15 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`
-  --> $DIR/coherence-fn-inputs.rs:15:1
+warning: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`
+  --> $DIR/coherence-fn-inputs.rs:16:1
    |
 LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
    | ----------------------------------------------- first implementation here
 LL | impl Trait for for<'c> fn(&'c u32, &'c u32) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)`
    |
+   = warning: the behavior may change in a future release
+   = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+   = note: `#[warn(coherence_leak_check)]` on by default
 
-error: aborting due to 1 previous error
+warning: 1 warning emitted
 
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
index 220fcd38b09..26e724c9061 100644
--- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
@@ -7,5 +7,21 @@ LL |         WHAT_A_TYPE => 0,
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
-error: aborting due to 1 previous error
+error[E0277]: the trait bound `for<'a, 'b> fn(&'a (), &'b ()): WithAssoc<T>` is not satisfied
+  --> $DIR/typeid-equality-by-subtyping.rs:44:51
+   |
+LL | fn unsound<T>(x: <One as WithAssoc<T>>::Assoc) -> <Two as WithAssoc<T>>::Assoc
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WithAssoc<T>` is not implemented for `for<'a, 'b> fn(&'a (), &'b ())`
+
+error[E0277]: the trait bound `for<'a, 'b> fn(&'a (), &'b ()): WithAssoc<T>` is not satisfied
+  --> $DIR/typeid-equality-by-subtyping.rs:47:1
+   |
+LL | / {
+LL | |     let x: <Two as WithAssoc<T>>::Assoc = generic::<One, T>(x);
+LL | |     x
+LL | | }
+   | |_^ the trait `WithAssoc<T>` is not implemented for `for<'a, 'b> fn(&'a (), &'b ())`
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs
new file mode 100644
index 00000000000..38abf59d844
--- /dev/null
+++ b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs
@@ -0,0 +1,38 @@
+// A regression test for #97156
+
+type One = for<'a> fn(&'a (), &'a ());
+type Two = for<'a, 'b> fn(&'a (), &'b ());
+
+mod my_api {
+    use std::any::Any;
+    use std::marker::PhantomData;
+
+    pub struct Foo<T: 'static> {
+        a: &'static dyn Any,
+        _p: PhantomData<*mut T>, // invariant, the type of the `dyn Any`
+    }
+
+    impl<T: 'static> Foo<T> {
+        pub fn deref(&self) -> &'static T {
+            match self.a.downcast_ref::<T>() {
+                None => unsafe { std::hint::unreachable_unchecked() },
+                Some(a) => a,
+            }
+        }
+
+        pub fn new(a: T) -> Foo<T> {
+            Foo::<T> { a: Box::leak(Box::new(a)), _p: PhantomData }
+        }
+    }
+}
+
+use my_api::*;
+
+fn main() {
+    let foo = Foo::<One>::new((|_, _| ()) as One);
+    foo.deref();
+    let foo: Foo<Two> = foo;
+    //~^ ERROR mismatched types [E0308]
+    //~| ERROR mismatched types [E0308]
+    foo.deref();
+}
diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr
new file mode 100644
index 00000000000..8c0d66bb0bc
--- /dev/null
+++ b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/higher-ranked-lifetime-equality.rs:34:25
+   |
+LL |     let foo: Foo<Two> = foo;
+   |                         ^^^ one type is more general than the other
+   |
+   = note: expected struct `my_api::Foo<for<'a, 'b> fn(&'a (), &'b ())>`
+              found struct `my_api::Foo<for<'a> fn(&'a (), &'a ())>`
+
+error[E0308]: mismatched types
+  --> $DIR/higher-ranked-lifetime-equality.rs:34:25
+   |
+LL |     let foo: Foo<Two> = foo;
+   |                         ^^^ one type is more general than the other
+   |
+   = note: expected struct `my_api::Foo<for<'a, 'b> fn(&'a (), &'b ())>`
+              found struct `my_api::Foo<for<'a> fn(&'a (), &'a ())>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs
index 230a0524df4..805fd7f1232 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs
@@ -2,8 +2,6 @@
 //
 // In particular, we test this pattern in trait solving, where it is not connected
 // to any part of the source code.
-//
-//@ check-pass
 
 trait Trait<T> {}
 
@@ -21,17 +19,17 @@ fn main() {
     // - The impl provides the clause `forall<'a> { (): Trait<fn(fn(&'a u32))> }`
     // - We instantiate `'a` existentially to get `(): Trait<fn(fn(&?a u32))>`
     // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a
-    //   "bidirectional" subtyping check, so we wind up with:
-    //   - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :-
-    //     - `fn(&!b u32) <: fn(&?a u32)`
-    //       - `&?a u32 <: &!b u32`
-    //         - `?a: !'b` -- solveable if `?a` is inferred to `'static`
-    //   - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :-
-    //     - `fn(&?a u32) <: fn(&?b u32)`
-    //       - `&?b u32 <: &?a u32`
-    //         - `?b: ?a` -- solveable if `?b` is inferred to `'static`
-    // - So the subtyping check succeeds, somewhat surprisingly.
-    //   This is because we can use `'static`.
+    //   "bidirectional" equality check, so we wind up with:
+    //   - `fn(fn(&?a u32)) == for<'b> fn(fn(&'b u32))` :-
+    //     - `fn(&!b u32) == fn(&?a u32)`
+    //       - `&?a u32 == &!b u32`
+    //         - `?a == !b` -- error.
+    //   - `fn(fn(&?a u32)) == for<'b> fn(fn(&'b u32))` :-
+    //     - `fn(&?b u32) == fn(&?a u32)`
+    //       - `&?a u32 == &?b u32`
+    //         - `?a == ?b` -- OK.
+    // - So the unification fails.
 
     foo::<()>();
+    //~^ ERROR implementation of `Trait` is not general enough
 }
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr
new file mode 100644
index 00000000000..385de795b18
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Trait` is not general enough
+  --> $DIR/hrtb-exists-forall-trait-covariant.rs:33:5
+   |
+LL |     foo::<()>();
+   |     ^^^^^^^^^^^ implementation of `Trait` is not general enough
+   |
+   = note: `()` must implement `Trait<for<'b> fn(fn(&'b u32))>`
+   = note: ...but it actually implements `Trait<fn(fn(&'0 u32))>`, for some specific lifetime `'0`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lub-glb/old-lub-glb-hr-eq.rs b/tests/ui/lub-glb/old-lub-glb-hr-eq.rs
index 97062ec91af..df288793608 100644
--- a/tests/ui/lub-glb/old-lub-glb-hr-eq.rs
+++ b/tests/ui/lub-glb/old-lub-glb-hr-eq.rs
@@ -3,8 +3,6 @@
 // error. However, now that we handle subtyping correctly, we no
 // longer get an error, because we recognize these two types as
 // equivalent!
-//
-//@ check-pass
 
 fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
     // The two types above are actually equivalent. With the older
@@ -13,6 +11,7 @@ fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
     let z = match 22 {
         0 => x,
         _ => y,
+        //~^ ERROR `match` arms have incompatible types [E0308]
     };
 }
 
diff --git a/tests/ui/lub-glb/old-lub-glb-hr-eq.stderr b/tests/ui/lub-glb/old-lub-glb-hr-eq.stderr
new file mode 100644
index 00000000000..ea8e53f2460
--- /dev/null
+++ b/tests/ui/lub-glb/old-lub-glb-hr-eq.stderr
@@ -0,0 +1,19 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/old-lub-glb-hr-eq.rs:13:14
+   |
+LL |       let z = match 22 {
+   |  _____________-
+LL | |         0 => x,
+   | |              - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8)`
+LL | |         _ => y,
+   | |              ^ one type is more general than the other
+LL | |
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _)`
+              found fn pointer `for<'a> fn(&'a _, &'a _)`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
index 039ca1fb58d..52b983cd12f 100644
--- a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
+++ b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
@@ -6,7 +6,6 @@
 // another -- effectively, the single lifetime `'a` is just inferred
 // to be the intersection of the two distinct lifetimes.
 //
-//@ check-pass
 //@ compile-flags:-Zno-leak-check
 
 use std::cell::Cell;
@@ -17,7 +16,9 @@ fn make_cell_aa() -> Cell<for<'a> fn(&'a u32, &'a u32)> {
 
 fn aa_eq_ab() {
     let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
+    //~^ ERROR mismatched types [E0308]
+    //~| ERROR mismatched types [E0308]
     drop(a);
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr
new file mode 100644
index 00000000000..9a88ce8756c
--- /dev/null
+++ b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/hr-fn-aau-eq-abu.rs:18:53
+   |
+LL |     let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
+   |                                                     ^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected struct `Cell<for<'a, 'b> fn(&'a _, &'b _)>`
+              found struct `Cell<for<'a> fn(&'a _, &'a _)>`
+
+error[E0308]: mismatched types
+  --> $DIR/hr-fn-aau-eq-abu.rs:18:53
+   |
+LL |     let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
+   |                                                     ^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected struct `Cell<for<'a, 'b> fn(&'a _, &'b _)>`
+              found struct `Cell<for<'a> fn(&'a _, &'a _)>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs b/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs
index 74164ad2aa2..a5696fc7796 100644
--- a/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs
+++ b/tests/ui/traits/next-solver/member-constraints-in-root-universe.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Znext-solver
-//@ check-pass
 
 trait Trait {
     type Ty;
@@ -11,6 +10,7 @@ impl Trait for for<'a> fn(&'a u8, &'a u8) {
 
 // argument is necessary to create universes before registering the hidden type.
 fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
+    //~^ ERROR the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed
     "hidden type is `&'?0 str` with '?0 member of ['static,]"
 }
 
diff --git a/tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr b/tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr
new file mode 100644
index 00000000000..7a9982f07f6
--- /dev/null
+++ b/tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr
@@ -0,0 +1,8 @@
+error: the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed
+  --> $DIR/member-constraints-in-root-universe.rs:12:16
+   |
+LL | fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+