Is it possible to have a function with a generic argument that converts that argument to an Arc with a generic trait? Something like this:
struct Foo<TypeOrTrait> {
arc: Option<Arc<TypeOrTrait>>,
}
impl<TypeOrTrait> Foo<TypeOrTrait> {
fn set<T>(&mut self, t: T) -> Arc<T> {
let arc = Arc::new(t);
self.arc = Some(arc.clone()); // Error
arc
}
}
The code complains that it can't convert Arc<T> to Arc<TypeOrTrait>.
In my code I don't have just the Arc that wraps TypeOrTrait, but a complex Arc<RwLock<Inner<TypeOrTrait>>> so I can't work around this by passing Arc<TypeOrTrait> to the set function.
The use case I have is that I want to have a collection that only implements a trait, but also want to have a way to access/modify the values using their original types. Something like this:
let foo: Foo<fmt::Display> = Foo { arc: None };
let value = foo.set(1u8);
assert_eq!(*value, 1u8);
assert_eq!(foo.bar.unwrap().to_string(), "1");
let value = foo.set(2u16);
assert_eq!(*value, 2u16);
assert_eq!(foo.bar.unwrap().to_string(), "2");
I was told that this would require higher kinded types, is that correct? If so, could it be emulated with something like what they do here (my Rust fu isn't on a par with that)?
If you have only few traits and types, you can use a custom trait:
If you have many traits or types... well... I think you don't have a solution. You can almost use
std::marker::Unsizeon nightly, but not, because you want to be able to use the same type for both too.