2 个不稳定版本
0.1.0 | 2023 年 8 月 2 日 |
---|---|
0.0.1 | 2023 年 7 月 13 日 |
#21 in #const-fn
21KB
176 行
Supertrait 🦹
Supertrait 是一个革命性的 crate,它通过多种与宏相关的技术,包括使用 macro_magic 以及在文档中展示的 "模块虫洞" 技术实现,使得自 2023 年 7 月起在稳定 Rust 中可以使用 默认关联类型 和 const fn 特性项。Supertrait 通过以下方式实现:在 #[supertrait]
和 #[impl_supertrait]
的文档中演示。
以下是一个端到端的示例
#[supertrait]
pub trait Fizz<T: Copy>: Copy + Sized {
type Foo = Option<T>;
type Bar;
const fn double_value(val: T) -> (T, T) {
(val, val)
}
const fn triple_value(val: T) -> (T, T, T);
fn double_self_plus(&self, plus: Self::Foo) -> (Self, Self, Self::Foo) {
(*self, *self, plus)
}
const fn interleave<I>(&self, a: T, b: I) -> (I, Self::Foo, T);
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct Buzz;
#[impl_supertrait]
impl<T: Copy> Fizz<T> for Buzz {
type Bar = usize;
const fn triple_value(val: T) -> (T, T, T) {
(val, val, val)
}
const fn interleave<I>(&self, a: T, b: I) -> (I, Self::Foo, T) {
(b, Some(a), a)
}
}
#[test]
const fn test_buzz_const() {
assert!(Buzz::triple_value(3).0 == 3);
let buzz = Buzz {};
match buzz.interleave('h', false).1 {
Some(c) => assert!(c == 'h'),
None => unreachable!(),
}
}
#[test]
fn test_buzz_default_associated_types() {
let buzz = Buzz {};
assert_eq!(buzz.double_self_plus(Some(3)), (buzz, buzz, Some(3)))
}
注意,在上面的 supertrait 中,我们能够使用具有完全泛型支持的默认关联类型和 const fn 特性项。
Supertraits 也被密封,这意味着通过 #[supertrait]
创建的 trait 只能在 #[impl_supertrait]
附加到 impl 语句的情况下实现。
默认关联类型以与最终添加到稳定 Rust 中时的功能几乎相同的方式实现。
const fn 特性项以 固有项 的形式在底层类型上实现,但它们的必要性由 #[impl_supertrait]
强制执行,而它们的类型界限由对每个填充的 const fn 特性项的非 const 实现的要求强制执行,这些实现由 #[impl_supertrait]
的扩展来填充。这些两种机制以及上述提到的特性密封技术共同确保了 const fn 特性项的存在和正确性得到与常规特性项同样强度的强制执行。
由于与现有固有项可能发生的命名冲突以及无法为包含 const fns 的 supertraits 执行泛型实现(因为在稳定 Rust 中,除了真实特性外,无法泛型实现任何东西),使用固有项作为实现 const fn 特性项的手段存在一些缺点。
话虽如此,当您在特性和超特类中使用 const fn 项时,继承是一种方便的后备方案,而超特类包含了目前稳定 Rust 中最方便的实现这种行为的方法。
依赖
~0.7–1.5MB
~30K SLoC