YAGNI, KISS, and @union

I’d like to propose removing unions from the specification to reduce some complexity and to make the wire-level protocol easier to comprehend. The tagged union introduces a second, variable-length data construct which reduces the ability to statically analyze bandwidth calculations, timing analysis, and memory usage. Furthermore, applications can chose to implement a tagged union as a combination of a custom data field and variable length array. This suggests that the construct is a non-essential feature that could be reintroduced later if YAGNI fails. Removing the feature later is, of course, much more difficult.

I’m reminded somewhat of CAN’s remote frame feature which turned into unused bloat and complexity. We should see if most applications end up reimplementing unions on top of UAVCAN before committing to pulling back into the standard.

I don’t think that YAGNI applies because we are using unions even in the standard data types already.

Unions are essential for creating complex generalized compositions where a set of nested types is extended with a collection of shared fields; as a publicly available example, see uavcan.metatransport.can.

Unions allow us to construct type-safe structures where the type designer can express the idea clearly in the code instead of using prose in comments.
The alternative you described with a variable-length array is a step back from the guarantees we provide in v1.0 at the moment.

Concerning the timing, memory, and other predictability issues, I don’t think unions are any different from variable-length arrays. The bit length computation rules seem to be identical in that respect for arrays and unions, so we don’t seem to be adding any extra variability with unions; and if we chose to avoid it, we would have to drop variable-length arrays also.

Unions are quite necessary and should stay.

MISRA 2008 and therefore autosar prohibit all use of unions in c and c++. At the very least we should remove all use of unions in the standard datatypes.

@union in DSDL is not the same as union in C++. The fact that we use the same keyword might be causing confusion though, but it’s not too late to change it if you want.

We need to look beyond the rule itself and consider the motivation behind it. Raw unions are banned by MISRA etc. because unchecked memory aliasing is fundamentally unsafe. There exist safe alternatives which also rely on memory aliasing but the safety is achieved via auxiliary state checking logic; in C++ that would be the new std::variant or, for example, in Rust there are enums. The reason unions are banned in C/C++ is therefore not that the concept itself is fundamentally defective but that it is implementation in those two languages is inadequate if safety is a concern. Seeing as unions themselves are not incompatible with safety, there is no reason we shouldn’t use them in UAVCAN.

Obviously, high-integrity C/C++ coding standards apply to C/C++ only, not DSDL. The mapping between DSDL and C/C++ (or any other language) can be defined to satisfy arbitrary application-specific constraints. C/C++ data structures generated from a DSDL union do not necessarily have to be raw unions themselves. For example, in Libuavcan v0, DSDL unions are generated into C++ structures; they could as well be std::variant or some homegrown typesafe alternative.

You can pry my unions from my cold, dead hands.

1 Like

1 Like