3个不稳定版本

0.2.1 2020年1月18日
0.2.0 2018年10月31日
0.1.0 2018年10月31日

#691 in 过程宏

MIT 许可证

10KB
104

Build Status Latest Version Rust Documentation

Rust Inherent Pub

动机

如果您在一个类型上实现了一个特质,除非您导入该特质,否则您只能使用该 impl 块中的方法

mod geometry {
    pub trait Length {
        fn length(&self) -> f64;
    }

    pub struct Vector(pub f64, pub f64);

    impl Length for Vector {
        fn length(&self) -> f64 {
            let Vector(x, y) = self;
            (x.powi(2) + y.powi(2)).sqrt()
        }
    }
}

fn main() {
    // Compilation error: we did not `use geometry::Length` so we can't access `length()`
    assert!(geometry::Vector(3.0, 4.0).length() == 5.0);
}

但如果是类型本身的自然成员,而不仅仅是特质中的方法呢?我们难道不能直接访问任何 Vectorlength 而不必明确告诉Rust我们在使用 Length 吗?

这就是 #[inherent_pub] 过程宏属性的作用!

用法

使用 #[inherent_pub],我们可以使得 length 可以在不导入 Length 特质的情况下使用——只需注解 impl 块并标记该方法为 pub

mod geometry {
    use inherent_pub::inherent_pub;

    pub trait Length {
        fn length(&self) -> f64;
    }

    pub struct Vector(pub f64, pub f64);

    #[inherent_pub]
    impl Length for Vector {
        pub fn length(&self) -> f64 {
            let Vector(x, y) = self;
            (x.powi(2) + y.powi(2)).sqrt()
        }
    }
}

fn main() {
    assert!(geometry::Vector(3.0, 4.0).length() == 5.0);
}

去糖化是如何工作的?

#[inherent_pub] 从方法和添加另一个 impl 块中移除了 pub,这些块中的固有方法会被重定向到特质方法。所以

impl Foo for Bar {
    #[inherent_pub]
    pub fn foo(self) {
        // Some code
    }
}

会被简化为

impl Foo for Bar {
    fn foo(self) {
        // Some code
    }
}

impl Bar {
    #[doc(hidden)]
    #[inline(always)]
    pub fn foo(self) {
        <Self as Foo>::(self)
    }
}

而不是处理像以单个下划线(_)开头或为单个下划线的特殊参数,如忽略参数或模式参数,#[inherent_pub] 只是将所有参数(除了 self)替换为泛型名称。所以

impl Foo for Bar {
    #[inherent_pub]
    pub fn foo(self, a: i32, (b, c): (i32, i32), _: i32) {
        // Some code
    }
}

会被简化为

impl Foo for Bar {
    fn foo(self, a: i32, (b, c): (i32, i32), _: i32) {
        // Some code
    }
}

impl Bar {
    #[doc(hidden)]
    #[inline(always)]
    pub fn foo(self, arg1: i32, arg2: i32, arg3: i32) {
        <Self as Foo>::(self, arg1, arg2, arg3)
    }
}

依赖项

~1.5MB
~35K SLoC