When should one collect &&T?

When we iter over a Vec<&T>, we get a reference to &T (ie &&T). While we can use this reference &&T to call methods of T, is there any benefit to collecting &&T rather than &T?

I was curious because that is the default behaviour of collect(). But I do not seem to see a case when I would not use either copied().collect() or cloned().collect().

#[derive(Debug)]
pub struct Line {
    pub constant: f64,
    pub slope: f64,
}
fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}

fn main(){
    let x = vec![&Line{constant:8.0, slope:90.0}, &Line{constant:80.0, slope:90.0}];
    print_type_of(&x); // Vec<&playground::Line>

    let y : Vec<_> = x.iter().collect();
    print_type_of(&y); // Vec<&&playground::Line>
    
    let z : Vec<_> = y.iter().collect();
    print_type_of(&z); // Vec<&&&playground::Line>
}

playground here

I would expect any case where it's beneficial to be extremely rare.

It's just the default behavior because .iter() has to deal with Vecs of all types, and .collect() has to deal with iterators of all types. You might have a Vec<NonCloneType> after all. Even if it could be specialized, consistency is a plus.

1 Like

But does &&T not always have a copy trait implemented (for any T) as it is just a pointer?

It does, but why do you expect it to be copied automatically whereas that's not the case for any other type?

It does. For clarity with the rest of this post, let's call it &&U though. You can always use .copied() (or .cloned()) on an iterator over &&U. But this is because &U: Copy (and Clone), not because &&U: Copy + Clone.

You can see this in the signature for .copied() (similarly for .cloned()):

fn copied<'a, T>(self) -> Copied<Self> where
    T: 'a + Copy,
    Self: Iterator<Item = &'a T>, 

You need an iterator over references, and the Copy bound applies to whatever is one level of reference lower. If you have an iterator over &&U, then T = &U.

But if I have an iterator over &NonCloneType, T = NonCloneType, and thus I can't call .copied() (or .cloned()). It's true that &NonCloneType: Copy + Clone, but that doesn't matter. It's the thing one below the outer reference that gets copied or cloned.

Playground.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.