ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.72k stars 2.53k forks source link

RLS: perform pre-ref coercions in more cases #19020

Open iacore opened 8 months ago

iacore commented 8 months ago

Zig Version

0.12.0-dev.2818+97290e0bf

Steps to Reproduce and Observed Behavior

save this file as inductive.zig

const Nat = union(enum) {
    Z,
    S: *const Nat,
};

test "zero is zero" {
    const a: Nat = Nat.Z;
    _ = Nat{ .S = &a };
    _ = Nat{ .S = &Nat.Z }; // try uncommenting this line
}
zig test inductive.zig

error:

❯ zig test inductive.zig
inductive.zig:9:15: error: expected type '*const inductive.Nat', found '*const @typeInfo(inductive.Nat).Union.tag_type.?'
    _ = Nat{ .S = &Nat.Z };
             ~^~~~~~~~~~
inductive.zig:9:15: note: pointer type child '@typeInfo(inductive.Nat).Union.tag_type.?' cannot cast into pointer type child 'inductive.Nat'
inductive.zig:1:13: note: enum declared here
const Nat = union(enum) {
            ^~~~~
inductive.zig:1:13: note: union declared here
const Nat = union(enum) {
            ^~~~~

Expected Behavior

The syntax should work, I think.

Workaround

_ = Nat{ .S = &Nat{ .Z = {} } };
mlugg commented 8 months ago

This ties into language design questions around RLS coercions with lvalues. The issue is essentially that we want @as(*const Nat, &Nat.Z) to coerce Z to the union type (from the tag type), but we don't want this for e.g. @as(*const Nat, &my_aggregate.nat_field) which is an indistinguishable syntax form.

Making this work is therefore a language proposal.

iacore commented 8 months ago

In https://ziglang.org/documentation/master/#toc-Type-Coercion-Unions-and-Enums, it says

Tagged unions can be coerced to enums, and enums can be coerced to tagged unions when they are comptime-known to be a field of the union that has only one possible value, such as void:

By this logic only comptime-known <A> will be coerced in expression &A.

mlugg commented 8 months ago

Yes, if this is implemented it can only work for comptime-known values in this specific case, but that's not relevant to the proposal. The proposal is to perform coercions of certain lvalue expressions as rvalues so as to make this code work.