Supporting conversions between multiple dispatch layers
(I initially misunderstood this issue as #18 (closed), but it's not related to the conversions themselves, it's related to a recursive hierarchy.)
It would be nice if we could convert (.into(),.try_into()) between multiple layers of enum_dispatch. For example
#[macro_use]
extern crate enum_dispatch;
//trait implementation
#[enum_dispatch]
trait Knob {}
//knob implementations
struct LinearKnob {}
impl Knob for LinearKnob {}
struct LogarithmicKnob {}
impl Knob for LogarithmicKnob {}
struct ExponentialKnob {}
impl Knob for ExponentialKnob {}
struct FactorialKnob {}
impl Knob for FactorialKnob {}
//knobs with 'good' runtimes
trait GoodKnob {}
#[enum_dispatch(GoodKnob)]
#[enum_dispatch(Knob)]
enum GoodKnobs {
LinearKnob,
LogarithmicKnob,
}
impl GoodKnob for LinearKnob {}
impl GoodKnob for LogarithmicKnob {}
//knobs with 'bad' runtimes
trait BadKnob {}
#[enum_dispatch(Knob)]
#[enum_dispatch(BadKnob)]
enum BadKnobs {
ExponentialKnob,
FactorialKnob,
}
impl BadKnob for ExponentialKnob {}
impl BadKnob for FactorialKnob {}
//all knobs
#[enum_dispatch(Knob)]
enum AnyKnob {
GoodKnobs,
BadKnobs
}
fn main() {
//this works
let specific = LinearKnob{};
let more_general: GoodKnobs = specific.into();
let most_general: AnyKnob = more_general.into();
//this doesn't
/*the trait `std::convert::From<LinearKnob>` is not implemented for `AnyKnob`
help: the following implementations were found:
<AnyKnob as std::convert::From<BadKnobs>>
<AnyKnob as std::convert::From<GoodKnobs>>
*/
let _most_general: AnyKnob = specific.into();
}
I have hierarchies like this example because some of my underlying types have common interfaces, modeled here as GoodKnob and BadKnob traits. You can imagine these as exposing some distinct methods specific to those knobs.
I could of course declare AnyKnob flatly to get a direct conversion, but then it would break the intermediate conversion instead:
//all knobs
#[enum_dispatch(Knob)]
enum AnyKnob {
ExponentialKnob,
FactorialKnob,
LinearKnob,
LogarithmicKnob
}
fn main() {
let specific = LinearKnob{};
let more_general: GoodKnobs = specific.into();
let most_general: AnyKnob = more_general.into();
//^^^^ the trait `std::convert::From<GoodKnobs>` is not implemented for `AnyKnob`
//help: the following implementations were found:
// <AnyKnob as std::convert::From<ExponentialKnob>>
// <AnyKnob as std::convert::From<FactorialKnob>>
// <AnyKnob as std::convert::From<LinearKnob>>
// <AnyKnob as std::convert::From<LogarithmicKnob>>
}
Currently I solve this by following the first listing and writing my own indirect conversions, but I believe a macro would improve this usecase.