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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! The main feature of this crate is the macro [`new!`] which can be used
//! to generate special unique and anonymous types.
//! In other words those are types that cannot be named and that are guardanteed
//! to always be different from every other type.
//!
//! The [`Unique`] trait can be used in trait bounds for requiring a type
//! to be generated from the [`new!`] macro.
//!
//! Those types can then be used to "tag" other types to make them uniquely identifiable.
//!
//! # Tagging
//!
//! To require a type to be uniquely identifiable simply add a generic with the
//! [`Unique`] trait bound:
//! ```
//! # use core::marker::PhantomData;
//! struct Struct<Tag: unique_type::Unique> {
//!     // other fields ...
//!     _marker: PhantomData<Tag>,
//! }
//! ```
//! Then when a value of that type is used, the [`new!`] macro can be used to declare the
//! unique type for that value:
//! ```
//! # use core::marker::PhantomData;
//! # struct Struct<Tag: unique_type::Unique> { _marker: PhantomData<Tag> }
//! # impl<Tag: unique_type::Unique> Struct<Tag> {
//! #     fn new() -> Self { Self { _marker: PhantomData } }
//! # }
//! # fn main() {
//! let value = Struct::<unique_type::new!()>::new(/* ... */);
//! # }
//! ```
//!
//! # Identifying
//!
//! Requiring two (or more) parameters/fields to have the same tag is as
//! easy as using the same generic for both of them:
//! ```
//! # struct Struct<Tag: unique_type::Unique> { _marker: core::marker::PhantomData<Tag> }
//! fn foo<Tag: unique_type::Unique>(a: Struct<Tag>, b: Struct<Tag>) {
//!     todo!()
//! }
//! ```
//! Now calling this function with two values that don't have the same tag will result in
//! a compiler error:
//! ```compile_fail E0308
//! # struct Struct<Tag: unique_type::Unique> { _marker: core::marker::PhantomData<Tag> }
//! # fn foo<Tag: unique_type::Unique>(a: Struct<Tag>, b: Struct<Tag>) { todo!() }
//! # fn main() {
//! let a: Struct<unique_type::new!()> = todo!();
//! let b: Struct<unique_type::new!()> = todo!();
//! // a and b now have two different tags
//! foo(a, b)
//! # }
//! ```

// Required for having &str as a const generic
#![feature(adt_const_params)]
#![feature(const_type_id)]
#![no_std]

use core::any::TypeId;

mod pvt {
    /// Private version of [`Unique`](super::Unique)
    ///
    /// This seals the trait so that it cannot be implemented outside of the crate
    pub trait Unique {}
}

/// An interface for reqiring unique types
///
/// The only types implementing this trait are the ones generated from [`new!`].
pub trait Unique: pvt::Unique {}

impl<T: pvt::Unique> Unique for T {}

/// A set of values that can only be constructed through the
/// [`Set::unique`] function
#[doc(hidden)]
#[derive(PartialEq, Eq)]
pub struct Set(TypeId);

impl Set {
    /// Constructs a new set of values that are unique from any other
    /// generated with this function
    ///
    /// # Safety
    ///
    /// This function is safe only if `T` is a unique and anonymous type.
    ///
    /// For example, this is a valid usage:
    /// ```
    /// # fn main() { unsafe {
    /// # use unique_type::Set;
    /// Set::unique(&(|| {}));
    /// # } }
    /// ```
    /// because from the [Rust Reference](https://doc.rust-lang.org/reference/types/closure.html):
    /// > A closure expression produces a closure value with a unique,
    /// > anonymous type that cannot be written out
    ///
    /// While this is an unsafe usage:
    /// ```
    /// # fn main() { unsafe {
    /// # use unique_type::Set;
    /// Set::unique(&0usize);
    /// # } }
    /// ```
    /// because the usize type can be named
    pub const unsafe fn unique<T>(_: &'static T) -> Self {
        Self(TypeId::of::<T>())
    }
}

/// A template-like type for generating unique types
///
/// The uniqueness of this type is based on the [`Set`] type which
/// can only be safely constructed with unique values thus making every
/// "specialization" of this type generate a different type-id
#[doc(hidden)]
pub struct Template<const T: Set>(());

impl<const T: Set> pvt::Unique for Template<T> {}

/// Generates a unique type that implements the [`Unique`] trait
///
/// # Example
///
/// Calling this macro twice will always generate two different types,
/// thus this will panic:
/// ```should_panic
/// # fn main() {
/// # use core::any::TypeId;
/// assert_eq!(
///     TypeId::of::<unique_type::new!()>(),
///     TypeId::of::<unique_type::new!()>()
/// );
/// # }
/// ```
///
/// And this won't even compile:
/// ```compile_fail E0308
/// # fn main() {
/// let a: unique_type::new!() = todo!();
/// let b: unique_type::new!() = a;
/// # }
/// ```
#[macro_export]
macro_rules! new {
    () => {
        $crate::Template<{
            // SAFETY: the const generics values are the one stated in the docs for Set
            unsafe { $crate::Set::unique(&(||{})) }
        }>
    };
}