unused/
lib.rs

1//! # About Unused
2//!
3//! The `unused` crate allows types to have unused generic parameters that do
4//! not act like they are owned.
5//!
6//! ## Feedback
7//!
8//! If you experience any issues or have any feedback, please feel free to open
9//! an issue on the
10//! [GitHub repository](https://github.com/patrick-gu/unused_rs/issues/new).
11//!
12//! ## `no_std` Support
13//!
14//! `unused` supports `no_std`.
15//!
16//! ## Example
17//!
18//! Imagine we have a struct `LazyFromStr`, which contains a <code>&'static [str]</code> and can
19//! lazily create a `T` using its [`FromStr`](core::str::FromStr) impl.
20//!
21//! To have `T` be a generic parameter of `LazyFromStr`, we can use a
22//! [`PhantomData`](core::marker::PhantomData). Otherwise, we get a
23//! compilation error that the parameter `T` is never used.
24//!
25//! ```
26//! use std::marker::PhantomData;
27//! use std::str::FromStr;
28//!
29//! struct LazyFromStr<T> {
30//!     str: &'static str,
31//!     phantom: PhantomData<T>,
32//! }
33//!
34//! impl<T: FromStr> LazyFromStr<T> {
35//!     fn create(&self) -> T {
36//!         match T::from_str(self.str) {
37//!             Ok(t) => t,
38//!             Err(_) => panic!(),
39//!         }
40//!     }
41//! }
42//! ```
43//!
44//! The issue with using [`PhantomData`](core::marker::PhantomData) is that
45//! `LazyFromStr<T>` is only [`Send`] and [`Sync`] if `T` also is, even though
46//! our `LazyFromStr<T>` does not own a `T`.
47//!
48//! This is where `unused` comes in.
49//!
50//! ```
51//! // We need to import `Unused`.
52//! use unused::Unused;
53//!
54//! struct LazyFromStr<T> {
55//!     str: &'static str,
56//!     // Use the `Unused` macro instead of `PhantomData`.
57//!     unused: Unused!(T),
58//! }
59//! # use std::str::FromStr;
60//! # impl<T: FromStr> LazyFromStr<T> {
61//! #     fn create(&self) -> T {
62//! #         match T::from_str(self.str) {
63//! #             Ok(t) => t,
64//! #             Err(_) => panic!(),
65//! #         }
66//! #     }
67//! # }
68//!
69//! use std::convert::Infallible;
70//! use std::rc::Rc;
71//!
72//! // `RcString` is not `Send` or `Sync`.
73//! struct RcString(Rc<String>);
74//!
75//! impl FromStr for RcString {
76//!     type Err = Infallible;
77//!
78//!     fn from_str(str: &str) -> Result<Self, Self::Err> {
79//!         Ok(Self(Rc::new(str.to_owned())))
80//!     }
81//! }
82//!
83//! let lazy: LazyFromStr<RcString> = LazyFromStr {
84//!     str: "a",
85//!     // Use `Unused` as a value.
86//!     unused: Unused,
87//! };
88//!
89//! use std::thread;
90//!
91//! // `lazy` is `Send` (even though `RcString` is not), so we can send it between threads.
92//! thread::spawn(move ||{
93//!     let _ = lazy.create();
94//! })
95//! .join()
96//! .unwrap();
97//! ```
98//!
99//! [By default, `Unused` makes generics invariant](Unused!#variances).
100//!
101//! See the [`Unused!`] macro for more examples.
102
103#![no_std]
104
105mod contravariant;
106mod covariant;
107mod end;
108mod inner;
109mod invariant;
110#[cfg(test)]
111mod tests;
112mod unused;
113
114#[doc(hidden)]
115pub use crate::contravariant::Contravariant;
116#[doc(hidden)]
117pub use crate::covariant::Covariant;
118#[doc(hidden)]
119pub use crate::end::End;
120#[doc(hidden)]
121pub use crate::invariant::Invariant;
122use crate::unused::UnusedImpl;
123#[doc(hidden)]
124pub use crate::unused::UnusedImpl::*;
125
126/// A container for unused generic types.
127///
128/// The `Unused` type can be created using the [`Unused!`] macro.
129///
130/// `Unused` can also be used as a value for any type `Unused<T>`:
131///
132/// ```
133/// use unused::Unused;
134///
135/// let _: Unused!(usize) = Unused;
136/// ```
137///
138/// See the [crate documentation](crate) for more information.
139pub type Unused<T> = UnusedImpl<T>;
140
141/// A macro that allows for the creation of [`type@Unused`] type containers.
142///
143/// A basic example of usage can be found in the [crate documentation](crate).
144///
145/// ## Usage
146///
147/// ```
148/// use unused::Unused;
149///
150/// struct Foo<A, B, C, D, E> {
151///     unused: Unused!(
152///         A,
153///         B,
154///         C: covariant,
155///         D: contravariant,
156///         E: invariant,
157///     ),
158/// }
159///
160/// ```
161///
162/// ## Variances
163///
164/// You can have different
165/// [type variances](https://doc.rust-lang.org/reference/subtyping.html) when
166/// working with `Unused`.
167///
168/// ### Invariant
169///
170/// Invariance is the default:
171///
172/// ```
173/// # use unused::Unused;
174/// let unused: Unused!(u8) = Unused;
175/// // is the same as:
176/// let unused: Unused!(u8: invariant) = Unused;
177/// ```
178///
179/// ### Covariance and Contravariance
180///
181/// To make `Foo` covariant over `A` and contravariant over `B`:
182///
183/// ```
184/// # use unused::Unused;
185/// struct Foo<A, B> {
186///     unused: Unused!(A: covariant, B: contravariant),
187/// }
188/// ```
189///
190/// ### Lifetimes
191///
192/// Variance is particularily useful when it comes to lifetimes:
193///
194/// ```
195/// # use unused::Unused;
196/// struct Foo<'foo> {
197///     unused: Unused!(&'foo (): covariant),   
198/// }
199///
200/// fn change_foo_lifetime<'a>(foo: Foo<'static>) -> Foo<'a> {
201///     foo
202/// }
203/// ```
204#[macro_export]
205macro_rules! Unused {
206    ($($type:ty $(: $variance:ident)?),+ $(,)?) => {
207        $crate::Unused::<$crate::__impl_Unused!($($type $(:$variance)?,)+)>
208    };
209}
210
211#[doc(hidden)]
212#[macro_export]
213macro_rules! __impl_Unused {
214    () => {
215        $crate::End
216    };
217    ($type:ty, $($types:ty $(:$variances:ident)?,)*) => {
218        $crate::Invariant::<$type, $crate::__impl_Unused!($($types $(: $variances)?,)*)>
219    };
220    ($type:ty: invariant, $($types:ty $(: $variances:ident)?,)*) => {
221        $crate::Invariant::<$type, $crate::__impl_Unused!($($types $(: $variances)?,)*)>
222    };
223    ($type:ty: covariant, $($types:ty $(: $variances:ident)?,)*) => {
224        $crate::Covariant::<$type, $crate::__impl_Unused!($($types $(: $variances)?,)*)>
225    };
226    ($type:ty: contravariant, $($types:ty $(: $variances:ident)?,)*) => {
227        $crate::Contravariant::<$type, $crate::__impl_Unused!($($types $(: $variances)?,)*)>
228    };
229}