use super::*;
pub trait FrpNode<Out> {
fn update(&self);
fn get(&self) -> (u32, Ref<Out>);
}
pub trait FrpNodeAny {
fn update(&self);
}
impl<T, Out> FrpNodeAny for T
where
T: FrpNode<Out>,
{
fn update(&self) {
FrpNode::<Out>::update(self);
}
}
I want to keep FrpNode<Out> the same. I want to declare a new trait FrpNodeAny which doesn't care about the Out parameter. (The goal is to create a vec of HETEROGENEOUS FrpNode<Out>'s, and call the update function on them.) EDIT: Vecs need to be HOMOGENEOUS, so instead of FrpNode<Out> with different Out parameter I want to have a FrpNodeAny trait.
Clearly I'm doing something wrong. What is the way to fix this?
EDIT: Sorry for not being clear. Here is the compile error:
|
12 | impl<T, Out> FrpNodeAny for T
| ^^^ unconstrained type parameter
You're not doing anything "wrong" per se, it's not possible to have a Vec<T> where T have different Out params in FrpNode<Out>s -- Vec<T>s must have every T the same size, and different Outs break that constraint.
One thing you can do is have a Vec<Box<dyn FrpNodeAny>>, and the boxed pointer would be the same size in the Vec, and thus you are holding different FrpNode<Out>s, just not storing the objects directly in the Vec.
This is problematic because you can't use FrpNodeAny without first proving FrpNode<Out> for some out. This just pushes the problem to the users, which is probably not what we want.
Associated Type appears to have fixed my problems.
Is there an "Rust Associated Types" cookbook somewhere? There has been quite a few times where I run into a problem, the solution is associated types, but even after it works, I still have no idea why the compiler is now happy. I'm looking for a list of pairs of the form
here's a problem you might try to solve via Generics, and get this error
Does my type consume Out (i.e. it's either part of the type of a struct field or a method parameter type)?
Does my type produce Out (i.e.it's part of a return type of a method)?
If you can answer the first question with a "No" and the second with a "Yes", it should probably be an associated type. That's what I know from contra- and covariance, the latter referring to what associated types are enabling.
Associated types won't help. They're not object-safe. (in order to create a trait object, the associated types must all be specified; dyn FrpNode<Out=T>)
Can't you split the functions that involve the generic type parameter out of the trait? So that you have an object-safe trait with update, and a non-object safe trait with get()?
(oops, posted wrong link at first!) Fixed link:Rust Playground
If you can answer the first question with a "No" and the second with a "Yes", it should probably be an associated type. That's what I know from contra- and covariance, the latter referring to what associated types are enabling.
FYI, associated types have nothing to do with what Rust calls variance. (associated types are always invariant in all of their type parameters, including the Self type). And associated types can frequently be input. The deciding factor is whether the type parameter should be uniquely specified by all of the other types, or if multiple possible choices should be allowed.