#New to Zig, dont understand this error message

1 messages · Page 1 of 1 (latest)

nova trout
#

Hello, I just started Zig like 15 minutes ago, and im currently learning about tagged enums. I am familiar with sum types because i've written rust code before, but i dont understnad the error im getting. this is my code:

test "tagged unions" {
    const RustOptionInt = union(enum) {
        none,
        some: i32,
    };

    var maybe_int = RustOptionInt.none;
    switch (maybe_int) {
        .none => {},
        .some => |*value| value.* += 1,
    }
    try expect(maybe_int == RustOptionInt.none);
}

and this is the error i get:

main.zig:75:35: error: incompatible types: '@typeInfo(main.test.tagged unions.RustOptionInt).Union.tag_type.?' and 'comptime_int'
        .some => |*value| value.* += 1,
                          ~~~~~~~~^~~~
main.zig:75:32: note: type '@typeInfo(main.test.tagged unions.RustOptionInt).Union.tag_type.?' here
        .some => |*value| value.* += 1,
                          ~~~~~^~
main.zig:75:38: note: type 'comptime_int' here
        .some => |*value| value.* += 1,
                                     ^

can someone please explain to me what is going on?

#

also,can you give tagged unions methods like you can with enums?

mossy fossil
#

wow this is the most confused i've been in a while staring at a zig error message.

nova trout
#

wow. and its my first one too lol

mossy fossil
#

it turns out that the way you inititalized maybe_int gives it the tag type of none, not the expected integer type.

lament palm
#

You use var maybe_int: RustOptionInt = .none; because it thinks that maybe_int is something like @typeInfo(main.test.tagged unions.RustOptionInt).Union.tag_type.? (Was also confused why it said that). v like that down there.

mossy fossil
#

in order to init properly:

var maybe_int: RustOptionInt = .none;
nova trout
#

this fixed it, but why does this example work?

test "switch on tagged union" {
    var value = Tagged{ .b = 1.5 };
    switch (value) {
        .a => |*byte| byte.* += 1,
        .b => |*float| float.* *= 2,
        .c => |*b| b.* = !b.*,
    }
    try expect(value.b == 3);
}

value is not given an explicit type

mossy fossil
#

that is another fine way to init value. it doesn't need an explicit type, a comptime_int is fine as long as it coerces to the payload type.

nova trout
#

ok i see. so just to clarify, the zig compiler inferred my variable as a tag type

mossy fossil
#

that way of initializing is similar to this, which actually works for void payload types:

var maybe_int = RustOptionInt{ .none = {} };
#

yeah, it was telling you that the capture was actually an enum type (the tag type).

nova trout
#

ah ok. so type inference works best when a payload can be coerced. in this case {} coerced to a void type

mossy fossil
#

it almost seems like its worthy of opening an issue. that was very confusing even for someone like me who has seen quite a bit of zig code

#

yeah the void payload init syntax can be a little confusing i guess

nova trout
#

another clarification: .{} is for tuples, and {} is for void?

mossy fossil
#

but in general, coercion works great for unions. you can always just use bare literals w/ out needing to use @as

#

yes that is correct. .{} used to work void void literals too, but that was changed

#

and now only {} works

nova trout
#

ok i understand. thank you for all your help!

mossy fossil
#

np zeroLike

nova trout
#

this question^^^

mossy fossil
#

oh yeah i forgot. yes you can.

#

any container type can have methods and other declarations.

nova trout
#

hell yeah

mossy fossil
#

like container level const/vars

nova trout
#

nice. thank you

mossy fossil
#

i think you should consider opening an issue for that. it was very confusing.

nova trout
#

i will consider that

atomic hinge
#

Huh, this one took me a second too - I thought if you referenced a void field it would give a union value by default which could decay to the tag where appropriate. I'm not sure whether this behaviour is intentional or not

mossy fossil
#

the thing that confused me is thinking the type of maybe_int was RustOptionInt rather than the tag type

night crane
#

.{} is a structure literal, which can coerce into a fixed array, struct, or union.

#

&.{} can coerce into a slice, or pointer to struct.

night crane