3个不稳定版本
0.2.1 | 2020年1月18日 |
---|---|
0.2.0 | 2018年10月31日 |
0.1.0 | 2018年10月31日 |
#691 in 过程宏
10KB
104 行
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);
}
但如果是类型本身的自然成员,而不仅仅是特质中的方法呢?我们难道不能直接访问任何 Vector
的 length
而不必明确告诉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