@safe accessing of union members
Paul Backus
snarwin at gmail.com
Wed Mar 17 18:01:43 UTC 2021
On Wednesday, 17 March 2021 at 16:43:25 UTC, Q. Schroll wrote:
> There was a discussion lately about overlapping pointers in
> unions, @safe and SumType.
>
> Obvious results: It is @safe overlapping some types with others
> and accessing them in @safe code and it is un- at safe to do so
> with other types.
>
> I had an insight that I wanted to share: invariants. A type has
> invariants if there could be bit-patterns that are invalid.
Yes. This is exactly what the "Background" section of the DIP
1035 [1] was trying to say.
> Breaking invariants incurs undefined behavior
Not necessarily. The statement
int* p = cast(int*) 0xDEADBEEF;
...does not have undefined behavior. You only get undefined
behavior if you actually dereference `p`.
In more general terms: undefined behavior doesn't come from the
values themselves, but from specific *operations* on those
values. The purpose of an invariant is to specify what conditions
are necessary to ensure defined behavior for a given operation.
> So, what kinds of union uses are @safe?
> Answer: If all members of the union have no invariants.
This is overly narrow. Unions themselves have no invariants, even
when their members do, because access to those members is
forbidden in @safe code, and there is no operation you can
perform on a union instance *as a whole* in @safe code whose
behavior is potentially undefined.
Some examples of things you can do with a union that are always
@safe, regardless of its members:
union U { int* ptr; int num; }
// Initialization is always @safe
U a = { num: 123 };
U b = { ptr: new int };
// Copying is always @safe
U c = b;
// Bitwise comparison is always @safe
assert(c is b);
// Casting memory to const(ubyte) is always @safe
writefln("Raw bytes: %(%02X %)",
*cast(const(ubyte)[U.sizeof]*) &c);
> When should the language (conservatively) assume an aggregate
> type (struct, class, etc.) has invariants?
The rules in the language spec [2] are mostly correct in this
regard, though they leave out `bool` (and enum types, though
that's a more debatable issue).
[1]
https://github.com/dlang/DIPs/blob/c39f6ac62210e0604dcee99b0092c1930839f93a/DIPs/DIP1035.md#background
[2] https://dlang.org/spec/function.html#safe-values
More information about the Digitalmars-d
mailing list