Hash::hash_slice - why Sized?

Implementation of Hash::hash_slice looks like this:

fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
where
    Self: Sized,
{
    for piece in data {
        piece.hash(state)
    }
}

But why does that require Self to be Sized? If you can implement Hash on unsized type, then why can't you hash slice of T and still can hash T?

Because slice items have to be Sized. It's not possible to create a slice of DSTs.

1 Like

You can hash a single unsized value because the hash method takes a reference so the size doesn't need to be known. With a slice you need to know the size of the type to be able to select an element from the slice correctly

I never thought about it, but that makes sense.
Also, I'm wondering why I missed such an important information, is this encoded in this sentence from slice documentation?

A dynamically-sized view into a contiguous sequence, [T]. Contiguous here means that elements are laid out so that every element is the same distance from its neighbors.

You can sort of conclude it from the “same distance from its neighbors” claim and the absence of a “maximum size for this slice” field (which could allow DSTs up to that size), but no, I wouldn't say it's properly documented there. (Or in the reference page.)

I think it's assumed because a slice is treated as a reference to an array, and one of the core properties of arrays is that you can access each element with simple pointer arithmetic (e.g. ptr = start + std::mem::size_of::<T>() * index). This only works because each element has a fixed size.

1 Like

Yes, "contiguous" and "same distance" together imply it.

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.