In Rust, references as well as Box<T>
, Rc<T>
, and Arc<T>
allow the creation of a trait object (eg, from Box<Type>
to Box<dyn Trait>
). But is there a way to allow the same conversion with a user-defined generic "smart pointer" type?
For example, MyBox<T>
is a thin wrapper around Box<T>
but the code below results in a compilation error:
use std::io::Write;
pub fn main() {
let std_box: Box<Vec<u8>> = Box::new(Vec::new());
let std_dyn: Box<dyn Write> = std_box;
// ^ this conversion is allowed.
let my_box: MyBox<Vec<u8>> = MyBox { t: Box::new(Vec::new()) };
let my_dyn: MyBox<dyn Write> = my_box;
// ^ this conversion is not allowed.
}
struct MyBox<T: ?Sized> {
t: Box<T>,
}
error[E0308]: mismatched types
--> traits/src/trait_objs.rs:7:36
|
7 | let my_dyn: MyBox<dyn Write> = my_box;
| ---------------- ^^^^^^ expected trait object `dyn std::io::Write`, found struct `Vec`
| |
| expected due to this
|
= note: expected struct `MyBox<dyn std::io::Write>`
found struct `MyBox<Vec<u8>>`
Unfortunately, it looks like the answer is "you don't" for Rust Stable. Rust is very conservative in which implicit coercions it allows. In particular, from the docs , we see the rule that's kicking in for Box
.
Coercion is allowed between the following types:
...
TyCtor(
T
) to TyCtor(U
), where TyCtor(T
) is one of
&T
&mut T
*const T
*mut T
Box<T>
and where
U
can be obtained fromT
by unsized coercion .
where the relevant unsized coercion rule is
T
todyn U
, whenT
implementsU + Sized
, andU
is object safe .
There's not much room for special casing there, at least not in the current version of Rust.
However, if you're willing to dip into Nightly-only features, then you get the exciting CoerceUnsized
trait , whose intended use case is... smart pointers to things which would coerce like a Box
would.
#![feature(unsize, coerce_unsized)]
use std::ops::CoerceUnsized;
use std::marker::Unsize;
impl<T, U> CoerceUnsized<MyBox<U>> for MyBox<T> where T: Unsize<U>, U: ?Sized {}
This tells Rust we can coerce MyBox<T>
to MyBox<U>
if T
is "basically the same" as U
, for an appropriate definition of "basically the same". No functions are required on the implementation; the trait impl
simply needs to exist.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.