Skip to content

Invalid slice assignment #23313

@hsyl20

Description

@hsyl20

Zig Version

0.15.0-dev.77+aa8aa6625

Steps to Reproduce and Observed Behavior

Consider the following reproducer (minimized from a larger codebase):

const std = @import("std");

const Foo = enum { x, y };
const Bar = union(enum) { a: void, b: void, v: u8 };

fn mk(u: u8) Bar {
    return .{ .v = u };
}

fn foo(f: Foo) !void {
    //const e:[]const Bar = switch (f) { 
    const e = switch (f) {
        .x => &.{ .a, mk(1) },
        .y => &.{ .b, mk(2) },
    };
    try std.testing.expectEqualSlices(Bar, &.{ .b, .{ .v = 2 } }, e);
}

test "bug" {
    try foo(.y);
}

It fails with:

> zig test test.zig
slices differ. first difference occurs at index 0 (0x0)

============ expected this output: =============  len: 2 (0x2)

[0]: test.Bar{ .b = void }
[1]: test.Bar{ .v = 2 }

============= instead found this: ==============  len: 2 (0x2)

[0]: test.Bar{ .a = void } <--- WRONG! Should be `.b`
[1]: test.Bar{ .v = 2 }

================================================

I've looked at the assembly and indeed the same literal value is assigned as first element in both cases.

	.type	.L__unnamed_6,@object
	.section	.rodata,"a",@progbits
.L__unnamed_6:
	.byte	0
	.zero	1
	.size	.L__unnamed_6, 2

       ...

	mov	cx, word ptr [rip + .L__unnamed_6] ; BAR's tag literal
	mov	word ptr [rbp - 8], cx
	mov	ax, word ptr [rax]
	mov	word ptr [rbp - 6], ax
	mov	eax, dword ptr [rbp - 8]
	mov	dword ptr [rbp - 4], eax
	mov	r8d, 2
	lea	rcx, [rbp - 4]
	mov	esi, offset __anon_561
	mov	rdx, r8
	call	testing.expectEqualSlices__anon_570

Notes:

  • adding a type ascription to const e (see the comment) seems to workaround the issue.
  • reversing the order of the switch alternatives changes the common tag that is used.

Expected Behavior

Assigned value should be correct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions