killercup / scribbles

Some notes on various topics.
https://deterministic.space
64 stars 11 forks source link

The Secret Life of Cows and `?Sized` rationale #18

Closed U007D closed 4 years ago

U007D commented 6 years ago

First of all, great post, thank you! Like many of your readers, I've seen Cows, known about Cows, but never really stopped to look at them long enough to wonder why I might use them. No more! :)

One question I have is around the rationale you provided for the ?Sized trait given in Cow's declaration:

?Sized is a funny one. By default, Rust requires types to be of a known size. ... if you have a reference to [an array of bytes], the reference itself can contain the length. ... Since a Cow should be able to contain a &[u8], we need to say “we don’t require this to be Sized

My thoughts on this are that a &[u8] is indeed sized--it's a fat pointer--always exactly 64 or 128 bits (depending on your platform), namely size_of::<*const u8> + size_of::<usize>. Further, as a fat pointer, the second element provides the size of the array, so one would think we have all the size information we could ever need...

I'll grant that the fat pointer's array size may not be known at compile time. But given that the Cow stores a &[u8] (and not a [u8]), shouldn't the fat pointer (which itself does have a known size at compile time) be all the Cow needs? I'm wondering why Cow needs more than this to work, or put another way, re-raises the question, why does Cow required ?Sized?

I hope my question makes sense. Thanks again for the excellent post.

killercup commented 6 years ago

Thanks, Brad!

So, yes, &[u8] is sized, but to implement Cow in a generic way and allow &[u8], we need to be able to talk about the properties of the [u8] part.

I didn't explain that very properly, sorry. Let me try again. Cow is generic over the T in &'a T, so the [u8] part of &'a [u8]. The array size is not know -- it doesn't need to. In your code, you'll only ever access it via a reference (i.e., a fat pointer).

Does that make sense?

Am 07.06.2018 um 16:21 schrieb Brad Gibson notifications@github.com:

First of all, great post, thank you! Like many of your readers, I've seen Cows, known about Cows, but never really stopped to look at them long enough to wonder why I might use them. No more! :)

One question I have is around the rationale you provided for the ?Sized trait given in Cow's declaration:

?Sized is a funny one. By default, Rust requires types to be of a known size. ... if you have a reference to [an array of bytes], the reference itself can contain the length. ... Since a Cow should be able to contain a &[u8], we need to say “we don’t require this to be Sized”

My thoughts on this are that a &[u8] is indeed sized--it's a fat pointer--always exactly 64 or 128 bits, depending on your platform, namely size_of::<*const u8> + size_of::. Further, as a fat pointer, the second element provides the size of the array, so one would think we have all the size information we could ever need... Which, of course, re-raises the question, why ?Sized?

Thanks again for the post.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

U007D commented 6 years ago

Ah, yes, it does. I was thinking about it more in terms of how it is used, but of course in terms of how it is implemented, T might not be sized. Thanks, @killercup!

killercup commented 6 years ago

Cool! I'll update the post with better wording before closing this :)