Crates.io | spidermeme |
lib.rs | spidermeme |
version | 0.1.0 |
source | src |
created_at | 2021-05-13 03:21:23.31418 |
updated_at | 2021-05-13 03:21:23.31418 |
description | Traits to test for type equality and type inequality |
homepage | |
repository | https://github.com/ErnWong/spidermeme |
max_upload_size | |
id | 396777 |
size | 30,714 |
WARNING: This crate currently depends on nightly rust unstable features. |
---|
Rust traits to check for type equality and type inequality.
Useful as a building block for more complicated compile-time constraints.
______________________________________________________________________________ |_________________________ _______ | | ___| | ______________ ___ | ___ | | | ___ .-` | | || / \ | | | | | | / \ | _..| | || | o o | | | | | | o | || || | || N Y P D \ / __ |___| | | | __ \ / __ || || | || ..-' '' \ o--| | | | |______ \ || || | ||____________ | \______\_____ | | | .' | \ \ || || | |_____________ |---__________/ | | _______.-' _.-/ \ | || || | | \ | \____ | | \_____.-' \ /\ | ||_ || | | \ / \____| | | \ /| | ___| ''| | | \ / | | | \ /__/ --..'--.| | | _____ ===== |_______| | | ======\ .. `-----| | / \ / \ |____________ | | / \ | ''| | _| | / ___ \ / _ \ | |____|_________ / | | | | | | | | | | / / \ \ / // / | | | | | |___ | |___| / / __ \ \ / / / / | '-. | | | | | \ /_/ \_\ / /' / / `-. '' | |_| | \____ / / \ \ | / \ \ `-. | | | // \ \__ \__\ \__\ `-----| | /| \___\ \ | \ \ | | /_| \ / \ / | |____________________________________________________\_/______|_|______________|
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.
use spidermeme::{SameTypeAs, NotSameTypeAs};
struct MyPair<T1, T2>(T1, T2);
trait ProcessPair {
fn process(&self);
}
impl<T1, T2> ProcessPair for MyPair<T1, T2> {
fn process(&self) {
println!("Pair of two different types.");
}
}
impl<T1, T2> MyPair<T1, T2>
where
T1: SameTypeAs<T2>,
{
fn process(&self) {
println!("Pair of same type.");
}
}
struct UniquePair<T1, T2>
where
T1: NotSameTypeAs<T2>,
{
a: T1,
b: T2,
}
impl<T1, T2> UniquePair<T1, T2>
where
T1: NotSameTypeAs<T2>,
{
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::<i32, f64>::new(1, 2.0);
// The following fails to compile:
// let y = UniquePair::<i32, i32>::new(1, 2);
}
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:
pub trait Same<T> {}
impl<T> Same<T> for T {}
This was inspired by numerous comments floating around on the web.
Type inequality uses negative_impls
and auto_traits
. A naive implementation would be like the following:
#![feature(negative_impls)]
#![feature(auto_traits)]
pub auto trait DifferentNaive {}
impl<T> !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:
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.
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(?).
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.
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.
#![feature(negative_impls)]
#![feature(auto_traits)]
#![feature(extended_key_value_attributes)]