Please tell me what you think!
Summary
These traits allow converting any object to a trait object. Specifically,
-
AsDynRef
converts&T
to&dyn SomeTrait
whereT: SomeTrait
-
AsDynMut
converts&mut T
to&mut dyn SomeTrait
whereT: SomeTrait
Motivation
I recently read a blog post explaining how to create a trait object whose concrete type is unknown at compile time. The optimal solution turns out to be complicated and non-obvious.
This proposal tries to change that; it allows us to implement the AsDynRef
and AsDynMut
traits for wrapper types. For example, we can implement them for an enum with two variants:
enum Either<L, R> {
Left(L),
Right(R),
}
impl<'a, A, B, TraitObj> AsDynMut<'a, TraitObj> for Either<A, B>
where
A: AsDynMut<'a, TraitObj>,
B: AsDynMut<'a, TraitObj>,
TraitObj: ?Sized + 'a,
{
fn as_dyn_mut(&'a mut self) -> &'a mut TraitObj {
match self {
Either::Left(l) => l.as_dyn_mut(),
Either::Right(r) => r.as_dyn_mut(),
}
}
}
This gives us a nice way to create a trait object, without knowing the concrete type at compile time:
let mut readable = if some_condition {
Either::Left(stdin())
} else {
Either::Right(File::open(path)?)
};
accepts_read_trait_object(readable.as_dyn_mut());
Guide-level explanation
The traits are defined like this:
pub trait AsDynRef<'a, TraitObj: ?Sized + 'a>: Sized {
fn as_dyn_ref(&'a self) -> &'a TraitObj;
}
pub trait AsDynMut<'a, TraitObj: ?Sized + 'a>: Sized {
fn as_dyn_mut(&'a mut self) -> &'a mut TraitObj;
}
These traits are automatically implemented for all types, for all traits they implement, if they're object safe.
An example how they would be implemented for types that implement Read
:
impl<'a, T: Read> AsDynRef<'a, dyn Read + 'a> for T {
fn as_dyn_ref(&'a self) -> &'a (dyn Read + 'a) {
self
}
}
impl<'a, T: Read> AsDynMut<'a, dyn Read + 'a> for T {
fn as_dyn_mut(&'a mut self) -> &'a mut (dyn Read + 'a) {
self
}
}
Since there is currently no mechanism to implement these traits for all trait objects, they have to be built into the compiler.
Drawbacks
This adds two more built-in traits, making the language more complicated.