Stream: t-lang/wg-unsafe-code-guidelines

Topic: Cow layout stability


Shnatsel (Mar 14 2020 at 11:08, on Zulip):

Has the layout of std::borrow::Cow been specified/stabilized yet?
I'm asking because somebody has found a way to implement it in a slightly more compact way (3 words instead of 4) and I'm wondering if a similar approach could be taken by std eventually: https://github.com/maciejhirsz/beef/

bjorn3 (Mar 14 2020 at 11:10, on Zulip):

beef only works for things that have a capacity field, while std::borrow::Cow works for all values.

HeroicKatora (Mar 14 2020 at 11:15, on Zulip):

It also doesn't differentiate between String::new() and a borrowed string, if I interpret the code correctly. That is mostly inconsequential for strings and vectors but still a slight detail.

simulacrum (Mar 14 2020 at 12:30, on Zulip):

(But regardless, Cow's layout is definitely not stable to my knowledge -- it's just a regular repr(Rust) enum, right?)

Elichai Turkel (Mar 16 2020 at 12:54, on Zulip):

if String's implementation will ever change to allocate on String::new() or "break their layout" beef will break..

bjorn3 (Mar 16 2020 at 12:59, on Zulip):

beef doesn't transmute a String. Instead it uses .as_mut_ptr(), .len() and .capacity() to deconstruct the string and later uses Vec::from_raw_parts + String::from_utf8_unchecked to reconstruct it: https://github.com/maciejhirsz/beef/blob/64b7812a3e10524a64404a47551e59a1a4b0f195/src/lib.rs#L86-L90

Elichai Turkel (Mar 16 2020 at 13:25, on Zulip):

you're right. my mistake, they don't care about the layout of string.

But can't we somehow enable the niche optimization we have for option on Cow too? because size_of::<Option<String>>() == size_of::<String>() so we could theoretically use that same bit for Cow for the discriminant

RalfJ (Mar 17 2020 at 12:14, on Zulip):

there's no bit though. there's a single "niche value", 0x0000000000000000

RalfJ (Mar 17 2020 at 12:14, on Zulip):

that's enough for None but not enough for Borrowed(ptr), because the latter has data to store

bjorn3 (Mar 17 2020 at 12:31, on Zulip):

For Cow<str> Owned could be represented as "ptr | len | capacity" while Borrowed could be represented as "0x0 | ptr | len".

RalfJ (Mar 18 2020 at 10:53, on Zulip):

@eddyb can we do this? ^

eddyb (Mar 18 2020 at 10:53, on Zulip):

lmao

eddyb (Mar 18 2020 at 10:54, on Zulip):

yeah uhhh I've been planning to work on that for ages

eddyb (Mar 18 2020 at 10:55, on Zulip):

@RalfJ @bjorn3 https://github.com/rust-lang/rust/issues/46213

eddyb (Mar 18 2020 at 10:56, on Zulip):

I also have some notes somewhere on how to do it

eddyb (Mar 18 2020 at 10:56, on Zulip):

I think it requires a slight redesign of the enum layout code, which might slow it down

eddyb (Mar 18 2020 at 10:56, on Zulip):

but basically we first compute the unoptimized layout and we only pick an optimization if it's smaller

eddyb (Mar 18 2020 at 10:57, on Zulip):

because tagged enums are always easier for LLVM to work with, IIRC, and this way we don't have to be clever about ensuring an optimized layout is smaller

eddyb (Mar 18 2020 at 10:57, on Zulip):

we just check

eddyb (Mar 18 2020 at 10:59, on Zulip):

so we can fix https://github.com/rust-lang/rust/issues/63866 that way then try to compute the layout for https://github.com/rust-lang/rust/issues/46213

eddyb (Mar 18 2020 at 11:01, on Zulip):

the best part is everything using layouts (miri, codegen) should work unchanged (barring any bugs) once we optimize layouts with non-empty niche variants

eddyb (Mar 18 2020 at 11:01, on Zulip):

the word "dataful" would be a lie at that point I guess

eddyb (Mar 18 2020 at 11:02, on Zulip):

@RalfJ @Shnatsel @bjorn3 lol https://github.com/rust-lang/rust/issues/46213#issuecomment-394388912

RalfJ (Mar 18 2020 at 11:16, on Zulip):

eddyb said:

the best part is everything using layouts (miri, codegen) should work unchanged (barring any bugs) once we optimize layouts with non-empty niche variants

I hope so :) that will put my understanding of niches to the test though ;)

eddyb (Mar 27 2020 at 23:41, on Zulip):

oh look at that https://github.com/rust-lang/rust/pull/70477

eddyb (Mar 27 2020 at 23:43, on Zulip):

I probably would've forgotten about it for another year tbh

RalfJ (Mar 28 2020 at 09:20, on Zulip):

I dont think I entirely understand what this does, but the wins in static_assert_size are nice :D

Last update: Jun 05 2020 at 22:40UTC