#macro-derive #derive #macro #utility

perfect-derive

提供所提议的 perfect_derive 宏的原型

4个版本

0.1.3 2023年10月19日
0.1.2 2023年9月16日
0.1.1 2023年5月12日
0.1.0 2022年11月13日

#1446过程宏

每月下载量 25
用于 parsy

MIT 许可证

37KB
906

Perfect Derive

crates.io docs.rs crates.io

添加衍生宏,以更好地限制生成的Copy、Debug等实现。

有关问题的总结,请参阅这篇博客文章

由于Rust无法处理循环限制,这些宏并不总是起作用。理想情况下,几年后这个crate将变得无操作,并且会有某种方法在纯Rust中完成这项工作,但在此之前这个技巧有助于清理一些代码。

问题

摘自上述Niko的博客

#[derive(Clone)]
struct List<T> {
    data: Rc<T>,
    next: Option<Rc<List<T>>>,
}

impl<T> Deref for List<T> {
    type Target = T;

    fn deref(&self) -> &T { &self.data }
}

目前,derive将生成一个需要T: Clone的实现,如下所示...

impl<T> Clone for List<T> 
where
    T: Clone,
{
    fn clone(&self) {
        List {
            value: self.value.clone(),
            next: self.next.clone(),
        }
    }
}

这里的T: Clone要求实际上是不必要的。这是因为在这个结构体中唯一的T位于一个Rc内部,因此是引用计数的。克隆Rc只会增加引用计数,实际上并不会创建一个新的T

使用perfect derive,我们可以做以下操作

#[perfect_derive(Clone)]
struct List<T> { /* as before */ }

这生成了实现上的“更好”的限制

impl<T> Clone for List<T> 
where
    Rc<T>: Clone, // type of the `value` field
    Option<Rc<List<T>>: Clone, // type of the `next` field
{
    fn clone(&self) { /* as before */ }
}

请注意,这些限制不需要T本身是可克隆的。

依赖关系

~0.5–1MB
~22K SLoC