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

Topic: Substitution principle


RalfJ (May 21 2019 at 18:50, on Zulip):

Did we ever document the following substitution principle for layouts as part of our layout/repr discussion? Or did we uncover some points that would contradict this principle?

Once size and alignment and niche of twp types are the same, you can assume that size and alignment and niche are the same when these two types are wrapped in arbitrary type constructors (excluding associated types).

It seems self-evident to me but what do I know.^^ Either way, this seems worth documenting?

Gankro (May 21 2019 at 18:55, on Zulip):

i assume there is also a caveat of "excluding potential extensions to specialization"

rkruppe (May 21 2019 at 18:56, on Zulip):

Need to exclude associated constants, too. Most kinds of parametricity-breaking constant expressions or type-level constructs (e.g. via specialization but there might be others, e.g. if TypeId::of was a const fn) can also violate this principle. And in a plausible future, there might also be associated const fns that allow newtypes to differ from their contents for layout purposes.

And then there's the broader problem that we haven't even formally committed to any kind of determinism in layout computation. Even struct A(i32); struct B(i32); can have different layouts as far as the current state of UCG is concerned.

Gankro (May 21 2019 at 18:58, on Zulip):

More specifically even if you guarantee size and align, field randomization may lead to a different niche position for MyGenericType<T>(T, u32), if the compiler chooses to randomize the order of .0 and .1 for, e.g., MyGenericType<&A> and MyGenericType<Box<A>>

RalfJ (May 21 2019 at 18:59, on Zulip):

"excluding associated anything" is really what I meant ;)

Gankro (May 21 2019 at 18:59, on Zulip):

(lost track if you have abandonned field randomization as a feature)

RalfJ (May 21 2019 at 18:59, on Zulip):

Even struct A(i32); struct B(i32); can have different layouts as far as the current state of UCG is concerned.

that is not in contradiction to my statement. "type constructors" are nominal, so A and B are different type constructors here.

rkruppe (May 21 2019 at 19:00, on Zulip):

Yes, but i32 and NonZeroI32 are nominally different types, hence...

RalfJ (May 21 2019 at 19:00, on Zulip):

...?

RalfJ (May 21 2019 at 19:00, on Zulip):

@Gankro

More specifically even if you guarantee size and align, field randomization may lead to a different niche position for MyGenericType<T>(T, u32), if the compiler chooses to randomize the order of .0 and .1 for, e.g., MyGenericType<&A> and MyGenericType<Box<A>>

that would indeed be a contradiction to my statement.

RalfJ (May 21 2019 at 19:01, on Zulip):

@rkruppe I dont know where you are going or what you are replying to.

rkruppe (May 21 2019 at 19:06, on Zulip):

I'm trying to say that we currently don't say layout computation of structs (enums too, unions? not sure) is deterministic, in particular it can depend on nominal types, treating two field types with same sizes, alignments, niches, etc. differently. So a better example than my previous one would be: given struct A<T>(T); we don't guarantee that A<i32> and A<u32> are laid out the same, even though we do guarantee that i32 and u32 have the same size, align, and niche.

rkruppe (May 21 2019 at 19:07, on Zulip):

Nominal types don't just matter "at the top level", so to speak

rkruppe (May 21 2019 at 19:09, on Zulip):

Current wording for reference: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/structs-and-tuples.md#default-layout-repr-rust

Matthew Jasper (May 21 2019 at 19:10, on Zulip):

Maybe I'm misunderstanding what's meant by niche here, but the whole point of NonZeroI32 is that it has a different niche to i32.

rkruppe (May 21 2019 at 19:10, on Zulip):

Ah, oops, you're right

rkruppe (May 21 2019 at 19:10, on Zulip):

Pretend I used #[repr(transparent)] struct WrapI32(i32); for the whole time

Gankro (May 21 2019 at 19:19, on Zulip):

I would think you could just use i32 and u32 :)

RalfJ (May 21 2019 at 19:20, on Zulip):

@rkruppe I see. then it becomes the same point as @Gankro's. I agree.

Last update: Nov 20 2019 at 11:25UTC