#traits #object #upcast #macro-generates

as-dyn-trait

一个属性宏,用于生成从特质对象中检索超特质的函数(向上转换)

2 个不稳定版本

0.2.0 2020 年 3 月 12 日
0.1.0 2020 年 3 月 9 日

5#upcast

Download history 1703/week @ 2023-11-26 1855/week @ 2023-12-03 1852/week @ 2023-12-10 1813/week @ 2023-12-17 1345/week @ 2023-12-24 1371/week @ 2023-12-31 3699/week @ 2024-01-07 2101/week @ 2024-01-14 1720/week @ 2024-01-21 1470/week @ 2024-01-28 1445/week @ 2024-02-04 2383/week @ 2024-02-11 1635/week @ 2024-02-18 2142/week @ 2024-02-25 2283/week @ 2024-03-03 581/week @ 2024-03-10

每月下载量 6,853

无许可证

38KB
939

一个属性宏,用于生成从特质对象中检索超特质的函数(向上转换)。

如果你有一个具有超特质的特质,有时你可能想要将特质对象向上转换。Rust 当前不支持此操作。

trait Super {}

trait Sub: Super {}

fn wants_upcast(sub: Box<dyn Sub>) {
    let s: Box<dyn Super> = sub;
    // do something with super.
}

这会导致以下错误

error[E0308]: mismatched types
 --> src/lib.rs:27:29
  |
8 |     let s: Box<dyn Super> = sub;
  |            --------------   ^^^ expected trait `Super`, found trait `Sub`
  |            |
  |            expected due to this
  |
  = note: expected struct `std::boxed::Box<dyn Super>`
             found struct `std::boxed::Box<(dyn Sub + 'static)>`

error: aborting due to previous error

as_dyn_trait 属性解决了这个问题

#[as_dyn_trait]
trait Super {}

trait Sub: Super {}

fn wants_upcast(sub: Box<dyn Sub>) {
    // s has type Box<dyn Super>.
    let s = sub.as_dyn_super();
    // do something with super.
}

为此,宏生成几个特质。对于一个名为 MyTrait 的特质,这些特质的名称和它们的方法是

  • AsDynMyTraitRef:
    • fn as_dyn_my_trait(&self) -> &dyn MyTrait;
    • fn as_dyn_my_trait_mut(&mut self) -> &mutdyn MyTrait;
  • AsDynMyTraitBox:
    • fn as_dyn_my_trait(self: Box<Self>) -> Box<dyn MyTrait>;
  • AsDynMyTraitRc:
    • fn as_dyn_my_trait(self: Rc<Self>) -> Rc<dyn MyTrait>;
  • AsDynMyTraitArc:
    • fn as_dyn_my_trait(self: Arc<Self>) -> Arc<dyn MyTrait>;
  • AsDynMyTraitPinRef:
    • fn as_dyn_my_trait(self: Pin<&Self>) -> Pin<&dyn MyTrait>;
    • fn as_dyn_my_trait_mut(self: Pin<&mut Self>) -> Pin<&mutdyn MyTrait>;
  • AsDynMyTraitPinBox:
    • fn as_dyn_my_trait(self: Pin<Box<Self>>) -> Pin<Box<dyn MyTrait>>;
  • AsDynMyTraitPinRc:
    • fn as_dyn_my_trait(self: Pin<Rc<Self>>) -> Pin<Rc<dyn MyTrait>>;
  • AsDynMyTraitPinArc:
    • fn as_dyn_my_trait(self: Pin<Arc<Self>>) -> Pin<Arc<dyn MyTrait>>;

这些特质自动为所有实现 MyTraitSized 类型实现。如果你想要为动态大小类型实现 MyTrait,你需要手动添加这些实现。由于你不能将 DST 转换为特质对象,因此这种实现总是会导致 panic。

为了使这些特质能够在特质对象上工作,它们都是 MyTrait 的自动超特质。

该属性支持几个选项。选项作为逗号分隔的列表传递给属性

#[as_dyn_trait(enable_pin = true, trait_name_prefix = DifferentName)]
trait Super {}
  • trait_name_prefix:用于生成的特质的命名前缀。默认是 AsDyn 后跟特质名称。
  • ref_trait_name:引用特质的名称。默认是带有后缀 Ref 的特质名称前缀。
  • box_trait_name:用于 Box 的特质的名称。默认是带有后缀 Box 的特质名称前缀。
  • rc_trait_name:用于 Rc 的特质的名称。默认是带有后缀 Rc 的特质名称前缀。
  • arc_trait_name:用于Arc<_>的特名字符串。默认是在特名字符串前加上Arc
  • pin_ref_trait_name:用于Pin<_>引用的特名字符串。默认是在特名字符串前加上PinRef
  • pin_box_trait_name:用于Pin<Box<_>>的特名字符串。默认是在特名字符串前加上PinBox
  • pin_rc_trait_name:用于Pin<Rc<_>>的特名字符串。默认是在特名字符串前加上PinRc
  • pin_arc_trait_name:用于Pin<Arc<_>>的特名字符串。默认是在特名字符串前加上PinArc
  • method_name:转换方法的名称。默认是as_dyn_后跟特名字符串(转换为小写蛇形)。
  • mut_method_name:可变引用转换方法的名称。默认是as_dyn_后跟特名字符串(转换为小写蛇形)和_mut
  • enable_ref:启用引用的转换。默认为true。
  • enable_box:启用Box<_>的转换。默认为true。
  • enable_rc:启用Rc<_>的转换。默认为true。
  • enable_arc:启用Arc<_>的转换。默认为true。
  • enable_pin:启用Pin<_>类型的转换。这些转换仅在相应的基指针转换也被启用的情况下生成。默认为false。

此属性不使用或生成任何不安全代码。

依赖项

~1.5MB
~34K SLoC