| WARNING: This crate currently depends on nightly rust unstable features. | |---|

spidermeme

Rust traits to check for type equality and type inequality.
Useful as a building block for more complicated compile-time constraints.

crates.io docs.rs ci Coverage


 ______________________________________________________________________________
|_________________________ _______      |    |                              ___|
| ______________   ___    |  ___  |     |    |             ___           .-` | |
||                /   \   | |   | |     |    |            /   \         | _..| |
||                | o o   | |   | |     |    |            o   |         ||  || |
||  N  Y  P  D    \   / __  |___| |     |    |         __ \   / __      ||  || |
||             ..-'   ''  \    o--|     |    |        |  |______  \     ||  || |
||____________ |   \______\_____  |     |    |       .'  |      \  \    ||  || |
|_____________ |---__________/    |     |  _______.-' _.-/      \  |    ||  || |
|              \         | \____  |     |    \_____.-' \        /\ |    ||_ || |
|               \       / \____|  |     |               \       /| | ___|  ''| |
|                \     /          |     |    |           \      /__/ --..'--.| |
|       _____     =====   |_______|     |    |            ======\   ..   `-----|
|      /     \   /     \  |____________ |    |           /       \  | ''| |   _|
|     /  ___  \  /  _   \ |             |____|_________ /         | |   | |  | |
|    |  |   |   /  / \   \                             /    //   /  |   | |  | |
|___ |  |___|  /  / __ \  \                           /   / /   / | '-. | |  | |
|     \       /_/        \_\                         /  /'  /  /   `-. '' |  |_|
|      \____ / /          \ \                       |  /    \  \      `-. |    |
|            //           \ \__                     \__\     \__\        `-----|
|           /|             \___\                     \  |     \ \              |
|          /_|                                       \ /      \ /              |
|____________________________________________________\_/______|_|______________|


## Provided traits ### `spidermeme::SameTypeAs` An automatically implemented marker trait to check if two types are equal. ### `spidermeme::NotSameTypeAs` An automatically implemented marker trait to check if two types aren't equal. ## Examples ```rust use spidermeme::{SameTypeAs, NotSameTypeAs}; struct MyPair(T1, T2); trait ProcessPair { fn process(&self); } impl ProcessPair for MyPair { fn process(&self) { println!("Pair of two different types."); } } impl MyPair where T1: SameTypeAs, { fn process(&self) { println!("Pair of same type."); } } struct UniquePair where T1: NotSameTypeAs, { a: T1, b: T2, } impl UniquePair where T1: NotSameTypeAs, { pub fn new(a: T1, b: T2) -> Self { Self { a, b } } } fn main() { // Prints "Pair of same type." MyPair(1_i32, 2_i32).process(); // Prints "Pair of two different types." MyPair(1_i32, 2_i16).process(); // Valid. let x = UniquePair::::new(1, 2.0); // The following fails to compile: // let y = UniquePair::::new(1, 2); } ``` ## How type equality works Type equality is pretty straightforward. The [`SameTypeAs`] trait has a blanket implementation using the same generic parameter. The basic principle looks like this when simplified: ```rust pub trait Same {} impl Same for T {} ``` This was inspired by numerous comments floating around on the web. ## How type inequality works Type inequality uses [`negative_impls`](doc.rust-lang.org/beta/unstable-book/language-features/negative-impls.html) and [`auto_traits`](doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html). A naive implementation would be like the following: ```rust #![feature(negative_impls)] #![feature(auto_traits)] pub auto trait DifferentNaive {} impl !DifferentNaive for (T, T) {} ``` However, this will give false negatives, as the auto trait will not be implemented for types that contain `(T, T)`. For example, the naive implementation will fail in the following example because `((i32, i32), (f64, f64))` contains `(i32, i32)` and `(f64, f64)`, both of which implement the `DifferentNaive` trait: ```rust,compile_fail use static_assertions::assert_impl_all; assert_impl_all!(((i32, i32), (f64, f64)): DifferentNaive); ``` This crate works around this by using a private named tuple instead of the primitive tuple, so that it is guaranteed that downstream crates will not test types that contain this named tuple. ## Known problems / quirks 1. Using both [`SameTypeAs`] and [`NotSameTypeAs`] to implement two impls for the same type will give: `error[E0119]: conflicting implementations`, probably due to the current limitations of Rust(?). 2. References to the same type, but with different lifetimes, are treated the same. This could be thought of as a "feature" if you squint hard enough. 3. For type equality in serious projects, you should probably try some [other crates](crates.io/search?q=type%20equal) by people who probably know better type theory and rust's type system. ## Unstable features ```rust #![feature(negative_impls)] #![feature(auto_traits)] #![feature(extended_key_value_attributes)] ```