| 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<T>

An automatically implemented marker trait to check if two types are equal.

spidermeme::NotSameTypeAs<T>

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(1i32, 2i32).process();

// Prints "Pair of two different types."
MyPair(1_i32, 2_i16).process();

// Valid.
let x = UniquePair::<i32, f64>::new(1, 2.0);

// The following fails to compile:
// let y = UniquePair::<i32, i32>::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<T> {} impl<T> Same<T> for T {}

This was inspired by numerous comments floating around on the web.

How type inequality works

Type inequality uses negative_impls and auto_traits. 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 by people who probably know better type theory and rust's type system.

Unstable features

```rust

![feature(negative_impls)]

![feature(auto_traits)]

![feature(extendedkeyvalue_attributes)]

```