2 unstable releases
0.2.0 | Mar 12, 2020 |
---|---|
0.1.0 | Mar 9, 2020 |
#5 in #upcast
7,384 downloads per month
38KB
939 lines
An attribute macro that generates methods for retrieving supertraits from trait-objects (upcasting).
If you have a trait with a supertrait, you sometimes want to upcast a trait object. Rust currently does not support this.
trait Super {}
trait Sub: Super {}
fn wants_upcast(sub: Box<dyn Sub>) {
let s: Box<dyn Super> = sub;
// do something with super.
}
This results in the following error:
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
The as_dyn_trait
attribute solves this problem:
#[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.
}
To achieve this, the macro generates several traits. For a trait MyTrait
, the names of these
traits and their methods are:
AsDynMyTraitRef
:fn as_dyn_my_trait(&self) -> &dyn MyTrait;
fn as_dyn_my_trait_mut(&mut self) -> &mut dyn 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<&mut dyn 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>>;
These traits are automatically implemented for all Sized
types that implement MyTrait
. If you
want to implement MyTrait
for dynamically sized types, you need to do add these implementations manually.
Since you cannot turn a DST into a trait object, such an implementation must always panic.
In order for those traits to work on trait objects, all of them are automatically supertraits of MyTrait
.
The attribute supports several options. The options are passed to the attribute as a comma-separated list:
#[as_dyn_trait(enable_pin = true, trait_name_prefix = DifferentName)]
trait Super {}
trait_name_prefix
: The prefix to use for the generated traits. Default isAsDyn
followed by the trait name.ref_trait_name
: The name of the trait for references. Default is the trait name prefix withRef
appended.box_trait_name
: The name of the trait forBox<_>
. Default is the trait name prefix withBox
appended.rc_trait_name
: The name of the trait forRc<_>
. Default is the trait name prefix withRc
appended.arc_trait_name
: The name of the trait forArc<_>
. Default is the trait name prefix withArc
appended.pin_ref_trait_name
: The name of the trait for Pin<_> references. Default is the trait name prefix withPinRef
appended.pin_box_trait_name
: The name of the trait forPin<Box<_>>
. Default is the trait name prefix withPinBox
appended.pin_rc_trait_name
: The name of the trait forPin<Rc<_>>
. Default is the trait name prefix withPinRc
appended.pin_arc_trait_name
: The name of the trait forPin<Arc<_>>
. Default is the trait name prefix withPinArc
appended.method_name
: The name of the conversion method. Default is theas_dyn_
followed by the trait name (converted to lower-snake-case).mut_method_name
: The name of the conversion method for mutable references. Default is theas_dyn_
followed by the trait name (converted to lower-snake-case) and_mut
.enable_ref
: Enables conversion of references. Default is true.enable_box
: Enables conversion ofBox<_>
. Default is true.enable_rc
: Enables conversion ofRc<_>
. Default is true.enable_arc
: Enables conversion ofArc<_>
. Default is true.enable_pin
: Enables conversion of thePin<_>
types. These are only generated conversion of the corresponding base pointer is also enabled. Default is false.
This attribute does not use or generate any unsafe code.
Dependencies
~1.5MB
~36K SLoC