I would like to be able to concisely write that a generic type implements a couple of From
traits. Is this possible (in stable or unstable Rust)? My current attempts (which weren't very successful), are as follows:
trait Versatile
where
Self: Sized,
String: From<Self>,
i64: From<Self>,
i32: From<Self>,
i16: From<Self>,
{
}
#[derive(Clone, Copy)]
struct Dummy;
impl From<Dummy> for String {
fn from(_: Dummy) -> Self {
"Dummy".to_string()
}
}
impl From<Dummy> for i64 {
fn from(_: Dummy) -> Self {
42
}
}
impl From<Dummy> for i32 {
fn from(_: Dummy) -> Self {
42
}
}
impl From<Dummy> for i16 {
fn from(_: Dummy) -> Self {
42
}
}
impl Versatile for Dummy {}
fn foo<D>(mut v: Vec<D>)
where
D: Versatile,
// Why do I need the following bounds?
// Aren't these implied by `Versatile`?
String: From<D>,
i64: From<D>,
i32: From<D>,
i16: From<D>,
/* imagine many more bounds here */
{
let s = String::from(v.pop().unwrap());
let big = i64::from(v.pop().unwrap());
let medium = i32::from(v.pop().unwrap());
let small = i16::from(v.pop().unwrap());
println!("{}, {}, {}, {}", s, big, medium, small);
}
// I can try to workaround:
trait Workaround: Into<String> + Into<i64> + Into<i32> + Into<i16> {}
impl<T: ?Sized> Workaround for T where
T: Into<String> + Into<i64> + Into<i32> + Into<i16>
{
}
fn bar<D>(mut v: Vec<D>)
where
// I can now write more concise:
D: Workaround,
{
// But then I can't use `From::from` anymore:
/*
let s = String::from(v.pop().unwrap());
let big = i64::from(v.pop().unwrap());
let medium = i32::from(v.pop().unwrap());
let small = i16::from(v.pop().unwrap());
*/
// Instead I am *required* to use `Into::into`:
let s: String = v.pop().unwrap().into();
let big: i64 = v.pop().unwrap().into();
let medium: i32 = v.pop().unwrap().into();
let small: i16 = v.pop().unwrap().into();
println!("{}, {}, {}, {}", s, big, medium, small);
}
fn main() {
foo(vec![Dummy; 4]);
bar(vec![Dummy; 4]);
}
Output:
Dummy, 42, 42, 42
Dummy, 42, 42, 42
Errors:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 1.21s
Running `target/debug/playground`
P.S.: I had a similar problem before, see: Generic impl TryFrom impossible due to orphan rules – what should I do? Maybe this one is very related to it, though I already "gave up" on hoping for default implementations (as needed/wanted in the previous thread). Right now, I'd be happy if I have to do all From
implementations manually (or via macro), as long as I can have a single trait to describe that all of these are supported.