1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
//! A trait for checking type equality.
//!
//! This crate implements the TypeEquals trick described in [rust-lang/rust#20041][comment].
//!
//! The following compiles:
//!
//! ```
//! use type_equals::TypeEquals;
//!
//! pub trait Owner {
//!     type Child1: Child;
//!     type Child2: Child;
//! }
//!
//! pub trait Child {
//!     type Owner: Owner;
//! }
//!
//! pub struct A;
//! impl Owner for A {
//!     type Child1 = B;
//!     type Child2 = C;
//! }
//!
//! pub struct B;
//! impl Child for B {
//!     type Owner = A;
//! }
//!
//! pub struct C;
//! impl Child for C {
//!     type Owner = A;
//! }
//!
//! pub fn want_child_one<T: Child>()
//! where
//!     <T::Owner as Owner>::Child1: TypeEquals<Other = T>,
//! {}
//!
//! pub fn want_child_two<T: Child>()
//! where
//!     <T::Owner as Owner>::Child2: TypeEquals<Other = T>,
//! {}
//!
//! pub fn this_works() {
//!     want_child_one::<B>();
//!     want_child_two::<C>();
//! }
//! ```
//!
//! Meanwhile, the following does not compile:
//! ```compile_fail
//! // A, B, C, want_child_one and want_child_two are declared identically.
//!
//! # use type_equals::TypeEquals;
//! #
//! # pub trait Owner {
//! #     type Child1: Child;
//! #     type Child2: Child;
//! # }
//! #
//! # pub trait Child {
//! #     type Owner: Owner;
//! # }
//! #
//! # pub struct A;
//! # impl Owner for A {
//! #     type Child1 = B;
//! #     type Child2 = C;
//! # }
//! #
//! # pub struct B;
//! # impl Child for B {
//! #     type Owner = A;
//! # }
//! #
//! # pub struct C;
//! # impl Child for C {
//! #     type Owner = A;
//! # }
//! #
//! # pub fn want_child_one<T: Child>()
//! # where
//! #     <T::Owner as Owner>::Child1: TypeEquals<Other = T>,
//! # {}
//! #
//! # pub fn want_child_two<T: Child>()
//! # where
//! #     <T::Owner as Owner>::Child2: TypeEquals<Other = T>,
//! # {}
//! #
//! pub fn this_does_not_work() {
//!     want_child_one::<C>();
//!     want_child_two::<B>();
//! }
//! ```
//!
//!   [comment]: https://github.com/rust-lang/rust/issues/20041#issuecomment-564369542.
pub trait TypeEquals {
    type Other: ?Sized;
}

impl<T: ?Sized> TypeEquals for T {
    type Other = Self;
}