diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 8682f4d3b7aed..17f932e78a105 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 7f27b35a54e4f..21b68ce998997 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 97ed4729bd0d9..c07ac1d3ace92 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 2c6987cc3f456..79a1afa469e89 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 659d99f025da0..e480414a35896 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>, } -#[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 c759fb6d5e4f4..1873bf0711fc4 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>( 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>); 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 9cbda95a4df7a..64033c351b1bf 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 0000000000000..d34b7a29623cf --- /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 0000000000000..71e196c32276e --- /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`.