Open Manishearth opened 11 months ago
That's a good question. I don't even know what the intention is here; this needs to be brought up with the lang team. (This is not a t-opsem question.)
Currently, we give Foo
the Uninhabited
ABI, so this does not act like a proper newtype. So the reality today is that repr(transparent)
does not work when one of the 1-ZST is an empty type, but the compiler fails to diagnose this properly.
It probably does not matter, though, because the ABI for an empty type is "Does not exist", and even if it did match ABI, it would be immediate UB to call a function with Foo
at either the call- or def-site.
However this might impact layout, e.g. Result<(), Foo>
vs Result<(), String>
might be different if enum discriminant encoding takes into account which variants are inhabited.
@chorman0773 it does matter when determining the impact of the transparent type on the repr of an enum wrapping it
though that also gets us into questions of transitivity https://github.com/rust-lang/unsafe-code-guidelines/issues/486
However this might impact layout, e.g. Result<(), Foo> vs Result<(), String> might be different if enum discriminant encoding takes into account which variants are inhabited.
#[repr(transparent)]
types don't necessarily propagate internal layout anyways.
The trivial case is that UnsafeCell<T>
and MaybeUninit<T>
is (by-spec) #[repr(transparent)]
over T
, but Option<T>
and Option<UnsafeCell<T>>
/Option<MaybeUninit<T>>
aren't the same layout.
Also works in reverse, NonZero{U,I}*
are all transparent over the corresponding {u,i}*
type by spec, but Option<NonZeroU32>
is not the same layout as Option<u32>
They don't always propagate, true. (NonZero
are not just transparent
though, they also add a niche with special magic, so they are out-of-scope here.)
But there's no fundamental reason why they shouldn't propagate through enum
. We anyway can't say this propagates through arbitrary wrappers since Wrapper<T>
may use a trait bound on T
and then use associated types and then obviously things can be arbitrarily different.
#[repr(transparent)]
types don't necessarily propagate internal layout anyways.
Oh, that's something that probably ought to be documented carefully.
But there's no fundamental reason why they shouldn't propagate through
enum
. We anyway can't say this propagates through arbitrary wrappers sinceWrapper<T>
may use a trait bound onT
and then use associated types and then obviously things can be arbitrarily different.
This would be a good guarantee to pin down!
Context: https://github.com/hyperium/hyper/issues/3500
The
repr(transparent)
RFC states:The reference states:
It's unclear if this applies to situations where a contained type is an empty type (
enum Empty {}
)For example, what are the implications of this?
From the RFC, this type is not "logically equvialent to a newtype", and
repr(transparent)
should not apply. From the reference, the other field is size 0 alignment 1, sorepr(transparent)
should make the repr the same asString
(I believe this is the current behavior in rustc), but it does feel like an edge case.It would be nice to have this explicitly documented, rather than inferred.