0

I'm trying to understand the need for the Trait:: and <T as Trait>:: method invocation syntax. In particular, I'm looking at the following function from this answer:

fn clone_into_array<A, T>(slice: &[T]) -> A
where
    A: Default + AsMut<[T]>,
    T: Clone,
{
    assert_eq!(
        slice.len(),
        std::mem::size_of::<A>() / std::mem::size_of::<T>()
    );

    let mut a = Default::default();
    <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
    a
}

It seems that the middle two method invocation lines can be rewritten as:

let mut a = A::default();
a.as_mut().clone_from_slice(slice);

I believe this is more readable, as we already know that A implements Default and AsMut<[T]> and we can invoke as_mut directly as a method instead of having to pass a to it explicitly.

However, am I missing a good reason for the linked answer to have written it more verbosely? Is it considered good style? Are the two semantically different under certain conditions?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
peterdn
  • 2,386
  • 1
  • 23
  • 24

1 Answers1

1

I agree with your rewrites — they are more clear and are what I would recommend for that function.

am I missing a good reason for the linked answer to have written it more verbosely?

My guess is that the author simply was tired of writing that function and stopped. If they took a look at it again, they might refine it to be shorter.

Is it considered good style?

I don't think there's a general community stylistic preference around this yet, other than the general "shorter is better until it isn't".

Are the two semantically different under certain conditions?

They shouldn't be.


There are times where the <>:: syntax is needed because otherwise it would be ambiguous. One example from a recent question:

let array = <&mut [u8; 3]>::try_from(slice);

Another time is when you don't have a nicely-named intermediate type or the intermediate type is ambiguous across multiple traits. One gross example is from a where clause but shows the same issue as an expression would:

<<Tbl as OrderDsl<Desc<Expr>>>::Output as LimitDsl>::Output: QueryId,

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366