about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs5
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs5
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs5
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs5
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs16
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr22
9 files changed, 63 insertions, 5 deletions
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 8682f4d3b7a..17f932e78a1 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -178,6 +178,11 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // A binder is equal to itself if it's structually equal to itself
+        if a == b {
+            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)?;
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 7f27b35a54e..21b68ce9989 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -103,6 +103,11 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // GLB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the GLB is
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index 97ed4729bd0..c07ac1d3ace 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -103,6 +103,11 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // LUB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the LUB is
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 2c6987cc3f4..79a1afa469e 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -213,6 +213,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // A binder is always a subtype of itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
         Ok(a)
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 659d99f025d..e480414a358 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -235,7 +235,7 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
 pub enum ImplSubject<'tcx> {
     Trait(TraitRef<'tcx>),
     Inherent(Ty<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index c759fb6d5e4..1873bf0711f 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -106,7 +106,7 @@ pub trait TypeRelation<'tcx>: Sized {
         T: Relate<'tcx>;
 }
 
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
         a: Self,
@@ -351,7 +351,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
     }
 }
 
-#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
+#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 9cbda95a4df..64033c351b1 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -217,7 +217,7 @@ static_assert_size!(TyKind<'_>, 32);
 /// * `GR`: The "return type", which is the type of value returned upon
 ///   completion of the generator.
 /// * `GW`: The "generator witness".
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct ClosureSubsts<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with a tuple containing the types of the upvars.
@@ -348,7 +348,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
 }
 
 /// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct GeneratorSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
new file mode 100644
index 00000000000..d34b7a29623
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
@@ -0,0 +1,16 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+fn id(
+    f: &dyn Fn(u32),
+) -> &dyn Fn(
+    &dyn Fn(
+        &dyn Fn(
+            &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+        ),
+    ),
+) {
+    f
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
new file mode 100644
index 00000000000..71e196c3227
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/hang-on-deeply-nested-dyn.rs:12:5
+   |
+LL |   ) -> &dyn Fn(
+   |  ______-
+LL | |     &dyn Fn(
+LL | |         &dyn Fn(
+LL | |             &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+LL | |         ),
+LL | |     ),
+LL | | ) {
+   | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
+LL |       f
+   |       ^ expected reference, found `u32`
+   |
+   = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+           the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+              found reference `&dyn Fn(u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.