Reputation: 7529
In my struct I have a from
function that takes a shared reference to a vector of elements of type T
and does some initialisation.
fn from(t: &Vec<T>) -> () {
// ...
for a in t {
// ...
}
for a in t {
// ...
}
}
I also have another function from_partial
that first performs some filtering on &Vec<T>
and wants to pass this reduced list of elements to from
. I don't want to clone so from_partial
constructs the vector as Vec<&T>
instead of Vec<T>
. I also don't want to duplicate the logic in from
as all in needs to do is loop over the vector and get a &T
to store somewhere.
In my concrete type example, I can assign both &Vec<&Bar>
and &Vec<Bar>
to from
let a: &Vec<&Bar> = &test.iter().collect();
let b: &Vec<Bar> = test;
Foo::from(a); // can assign &Vec<&Bar>
Foo::from(b); // can assign &Vec<Bar>
However when working with generic types, I am unable to do so:
fn from_partial(t: &Vec<T>) -> () {
// Here a function is called that does some filtering on &Vec<T>
// and returns &Vec<&T>, but omitting for brevity.
let example: &Vec<&T> = &t.iter().collect();
Self::from(example); // cannot assign &Vec<&T> to &Vec<T>?
}
Here's the MVCE (Playground):
struct Foo<T> {
t: T,
}
struct Bar {}
impl<T> Foo<T> {
fn from(t: &Vec<T>) -> () {
let mut v = Vec::new();
for a in t {
// ...
v.push(Foo { t: a })
}
for a in t {
// ...
v.get(0);
}
}
fn from_partial(t: &Vec<T>) -> () {
// Here a function is called that does some filtering on &Vec<T>
// and returns &Vec<&T>, but omitting for brevity.
let example: &Vec<&T> = &t.iter().collect();
Self::from(example); // cannot assign &Vec<&T> to &Vec<T>?
}
}
fn main() {}
fn test(test: &Vec<Bar>) {
let a: &Vec<&Bar> = &test.iter().collect();
let b: &Vec<Bar> = test;
Foo::from(a); // can assign &Vec<&Bar>
Foo::from(b); // can assign &Vec<Bar>
}
Is there any sort of constraint I can add on T
that would make this possible? To essentially prevent me from duplicating exactly the same logic in from
twice.
Upvotes: 4
Views: 579
Reputation: 26197
You need to replace Self::from(example);
with Foo::from(example);
.
Consider that T
is Bar
, then your from_partial
call takes &Vec<Bar>
. The issue is that Self
then represents Foo::<Bar>
, but you're trying to call from
with &Bar
, i.e. you need Foo::<&Bar>
.
fn from_partial(t: &Vec<T>) -> () {
let example: &Vec<&T> = &t.iter().collect();
Foo::from(example);
}
Upvotes: 5