Why can't values be casted to unions?

The syntax of .{.tag = value} seems unnecessary when the union only has one field of that type. Why can’t it be an implicit cast?

The fields of a tagged union are not necessarily of different types. They may be of the same type.

Edit: Sorry I missed your emphasis on the union having one field of that type.

However, the solution you discuss could still cause the compiler to be silent when the logic drifts.

Consider a union:

const ObjectId = union(enum) {
    small: u32,
    large: u64,
    pub fn initSmall(size: u32) ObjectId  {
        return .{ .small = size };
    }
};

One day, you modify it:

const ObjectId = union(enum) {
    small: u16,
    midium: u32,
    large: u64,
    pub fn initSmall(size: u32) ObjectId {
        return .{ .small = size };
    }
};

The above code will produce an compiler error:

test.zig:381:32: error: expected type 'u16', found 'u32'
            return .{ .small = size };
                               ^~~~

If this tag specification is allowed to be omitted, then the related errors will be silent after the contents of the union are changed.

Explicit is better than implicit, believe this zen, it is always right.

8 Likes

On the topic of explicit is better than implicit, you should have explicitly listed the issues with their proposal.

In the context of the above example change:

  • the resulting value could be different after changing the union, especially important for a tagged union which you almost certainly branch on
  • the function now has the wrong behaviour, which would be hidden by the implicit coercion
  • It is quite the extreme implicit coercion, most prefer such a change in type to be explicit
    • optionals and error unions are an exception, as they are conceptually much simpler than an arbitrary user defined type, they are also more fundamental.

Another language effect here is that .tag = expression sets result type for the expression, which drives type inference:

So, by adding correction and loosing result type, you might end up just pushing verbosity elsewhere.

(aside, but I zigging love Zig’s type inference, its in the perfect sweet spot where it’s easy to read, very fast to compile, and requires annotations exactly at those places which would be unclear for the human reader anyway)

6 Likes