MemoryLayout.size of an enum?

This isn't safe; RawRepresentable.RawValue can be any type, including a reference type. You can't necessarily just materialise one from untrusted bytes.

I can recall suggestions that BitwiseCopyable could allow for these constructs to be written safely - so you could write <T: RawRepresentable> where T.RawValue: BitwiseCopyable. I'm not entirely sure that is safe, either.

For an integer or float, it doesn't matter; it's not a safety issue. You may read an unexpected/nonsense value, but every bit-pattern is defined. If you load an integer or float from some unknown memory address, the compiler obviously won't assume any particular value in a way that UB could result if the assumption was incorrect.

But for an enum, if you load an enum from random bytes, it may have a bit-pattern that doesn't correspond to any of its cases. So when performing an exhaustive switch, it may be that you do not land in any branch:

enum MyEnum: BitwiseCopyable {
  case a, b, c
} // size: 1 byte

let myEnumValue = RandomBytes(1).load(as: MyEnum.self)

var x: SomeClass
switch myEnumValue {
case .a: x = SomeClass(...)
case .b: x = SomeClass(...)
case .c: x = SomeClass(...)
}
// Is 'x' definitely initialised here?
// What if myEnumValue is none of a/b/c?

I don't think the compiler can/would guarantee that all enum switches land in a deterministic branch, even if the enum has an invalid bit-pattern. At the same time, MyEnum is unquestionably BitwiseCopyable. So clearly BitwiseCopyable isn't the constraint we're looking for.

To connect this directly to the problem, if T.RawValue was another enum, it is theoretically possible that T.init?(_: RawValue) wouldn't actually initialise the T. And then switching over the resulting T could also lead to UB.

In order for this to be truly safe (given that it is generic), we need a constraint where every bit-pattern is an allowed value. Then you could truly read values from untrusted ("random") data without fear of UB.

Or you could just limit this to the one integer type this thing needs to support.

4 Likes