1 个不稳定版本
0.1.0 | 2021 年 5 月 13 日 |
---|
#1698 in Rust 模式
18KB
警告:该crate目前依赖于nightly rust不稳定功能。 |
---|
spidermeme
Rust 特性,用于检查类型等价和类型不等价。
可以作为更复杂编译时约束的构建块。
______________________________________________________________________________ |_________________________ _______ | | ___| | ______________ ___ | ___ | | | ___ .-` | | || / \ | | | | | | / \ | _..| | || | o o | | | | | | o | || || | || N Y P D \ / __ |___| | | | __ \ / __ || || | || ..-' '' \ o--| | | | |______ \ || || | ||____________ | \______\_____ | | | .' | \ \ || || | |_____________ |---__________/ | | _______.-' _.-/ \ | || || | | \ | \____ | | \_____.-' \ /\ | ||_ || | | \ / \____| | | \ /| | ___| ''| | | \ / | | | \ /__/ --..'--.| | | _____ ===== |_______| | | ======\ .. `-----| | / \ / \ |____________ | | / \ | ''| | _| | / ___ \ / _ \ | |____|_________ / | | | | | | | | | | / / \ \ / // / | | | | | |___ | |___| / / __ \ \ / / / / | '-. | | | | | \ /_/ \_\ / /' / / `-. '' | |_| | \____ / / \ \ | / \ \ `-. | | | // \ \__ \__\ \__\ `-----| | /| \___\ \ | \ \ | | /_| \ / \ / | |____________________________________________________\_/______|_|______________|
提供的特性
spidermeme::SameTypeAs<T>
一个自动实现的标记特性,用于检查两个类型是否相等。
spidermeme::NotSameTypeAs<T>
一个自动实现的标记特性,用于检查两个类型是否不相等。
示例
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);
}
类型等价的工作方式
类型等价非常直接。`SameTypeAs` 特性使用相同的泛型参数有一个空白实现。当简化时,基本原理如下
pub trait Same<T> {}
impl<T> Same<T> for T {}
这受到了网络上许多评论的启发。
类型不等价的工作方式
类型不等价使用 negative_impls
和 auto_traits
。一个简单的实现可能如下所示
#![feature(negative_impls)]
#![feature(auto_traits)]
pub auto trait DifferentNaive {}
impl<T> !DifferentNaive for (T, T) {}
然而,这将导致错误的阴性结果,因为对于包含(T, T)
类型的自动特性将不会实现。例如,在以下示例中,原始实现将失败,因为((i32, i32), (f64, f64))
包含(i32, i32)
和(f64, f64)
,它们都实现了DifferentNaive
特性
use static_assertions::assert_impl_all;
assert_impl_all!(((i32, i32), (f64, f64)): DifferentNaive);
这个crate通过使用私有命名元组而不是原始元组来解决这个问题,因此可以保证下游crate不会测试包含此命名元组的类型。
已知问题/怪癖
-
使用
SameTypeAs
和NotSameTypeAs
同时实现同一类型的两个impl将导致:error[E0119]: conflicting implementations
,这可能是由于Rust当前限制(?)。 -
对同一类型的引用,但具有不同的生命周期,被当作相同对待。如果你足够用力地眯眼,这可能被认为是一个“特性”。
-
对于重大项目中类型相等的问题,你可能会尝试一些由可能更了解类型理论和Rust类型系统的人编写的其他crate。
不稳定的功能
#![feature(negative_impls)]
#![feature(auto_traits)]
#![feature(extended_key_value_attributes)]