Macro CoercePointee
macro_rules! CoercePointee { ... }
Derive macro that makes a smart pointer usable with trait objects.
What this macro does
This macro is intended to be used with user-defined pointer types, and makes it possible to perform coercions on the pointee of the user-defined pointer. There are two aspects to this:
Unsizing coercions of the pointee
By using the macro, the following example will compile:
use CoercePointee;
use Deref;
;
Without the #[derive(CoercePointee)] macro, this example would fail with the following error:
error[E0308]: mismatched types
--> src/main.rs:11:44
|
11 | let ptr: MySmartPointer<dyn MyTrait> = ptr;
| --------------------------- ^^^ expected `MySmartPointer<dyn MyTrait>`, found `MySmartPointer<i32>`
| |
| expected due to this
|
= note: expected struct `MySmartPointer<dyn MyTrait>`
found struct `MySmartPointer<i32>`
= help: `i32` implements `MyTrait` so you could box the found value and coerce it to the trait object `Box<dyn MyTrait>`, you will have to change the expected type as well
Dyn compatibility
This macro allows you to dispatch on the user-defined pointer type. That is, traits using the type as a receiver are dyn-compatible. For example, this compiles:
use CoercePointee;
use Deref;
;
// You can always define this trait. (as long as you have #![feature(arbitrary_self_types)])
// But using `dyn MyTrait` requires #[derive(CoercePointee)].
If you remove the #[derive(CoercePointee)] annotation from the struct, then the above example
will fail with this error message:
error[E0038]: the trait `MyTrait` is not dyn compatible
--> src/lib.rs:21:36
|
17 | fn func(self: MySmartPointer<Self>);
| -------------------- help: consider changing method `func`'s `self` parameter to be `&self`: `&Self`
...
21 | fn call_func(value: MySmartPointer<dyn MyTrait>) {
| ^^^^^^^^^^^ `MyTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/lib.rs:17:19
|
16 | trait MyTrait {
| ------- this trait is not dyn compatible...
17 | fn func(self: MySmartPointer<Self>);
| ^^^^^^^^^^^^^^^^^^^^ ...because method `func`'s `self` parameter cannot be dispatched on
Requirements for using the macro
This macro can only be used if:
- The type is a
#[repr(transparent)]struct. - The type of its non-zero-sized field must either be a standard library pointer type
(reference, raw pointer,
NonNull,Box,Rc,Arc, etc.) or another user-defined type also using the#[derive(CoercePointee)]macro. - Zero-sized fields must not mention any generic parameters unless the zero-sized field has
type
PhantomData.
Multiple type parameters
If the type has multiple type parameters, then you must explicitly specify which one should be used for dynamic dispatch. For example:
#
# use ;
Specifying #[pointee] when the struct has only one type parameter is allowed, but not required.
Examples
A custom implementation of the Rc type:
use CoercePointee;
use Deref;
use NonNull;