#traits #const-fn #stable #supertraits #macro

supertrait

Supertrait 允许在稳定 Rust 中使用默认关联类型和 const fn 特性项

2 个不稳定版本

0.1.0 2023 年 8 月 2 日
0.0.1 2023 年 7 月 13 日

#21 in #const-fn

MIT 许可证

21KB
176

Supertrait 🦹

Crates.io docs.rs Build Status MIT License

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