Skip to content

Compiler crash with incompatible type when doing reflection #14715

@kuon

Description

@kuon

Zig Version

0.11.0-dev.1796+c9e02d3e69 (llvm 15.0.6)

Steps to Reproduce and Observed Behavior

I have some code that convert elixir struct into zig struct in a NIF, and for this I have an approach a bit similar to the json lib in std.

I have found that having an optional slice triggers a compiler error, I was able to reduce the bug into a minimal example below.

In src/main.zig

const std = @import("std");
const meta = std.meta;
const mem = std.mem;

pub const Data = struct {
    foo: ?[]const u8 = null,
};

export fn do_something() void {
    var data: Data = mem.zeroes(Data);

    populate(&data) catch unreachable;
    std.debug.print("bug: {any}\n", .{data});
}

fn populate(dest: anytype) !void {
    const T = @TypeOf(dest.*);
    switch (@typeInfo(T)) {
        .Struct => {
            const key = "foo";

            inline for (comptime meta.fieldNames(T)) |n| {
                if (mem.eql(u8, n, key)) {
                    try populate(
                        &@field(dest, n),
                    );
                }
            }
        },
        .Optional => |O| {
            dest.* = mem.zeroes(O.child);
            try populate(&dest.*.?);
            return;
        },
        .Pointer => |ptr_info| {
            switch (ptr_info.size) {
                .Slice => {
                    if (ptr_info.child == u8) {
                        dest.* = "hello";
                    }
                    return;
                },
                else => return error.UnsupportedType,
            }
        },
        else => return error.UnsupportedType,
    }
}

in builg.zig

const std = @import("std");

pub fn build(b: *std.Build) void {
    const optimize = b.standardOptimizeOption(.{
        .preferred_optimize_mode = .ReleaseSafe,
    });

    const step = b.step("lib", "Compile library");

    const lib = b.addSharedLibrary(.{
        .name = "testlib",
        .root_source_file = .{ .path = "./src/main.zig" },
        .optimize = optimize,
        .target = .{},
    });

    lib.install();
    lib.linkLibC();
    step.dependOn(&lib.step);
}

Running zig build lib

$ zig build lib
LLVM Emit Object... invalid type ref
!1772 = distinct !DIGlobalVariable(name: "zeroes__anon_630__anon_858", linkageName: "mem.zeroes__anon_630__anon_858", scope: !1709, file: !1709, line: 236, type: zig: /home/kuon/Repos/aur/llvm15/src/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = ValueAsMetadata; From = const Metadata]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
error: testlib...
error: The following command terminated unexpectedly:
/usr/bin/zig build-lib /home/kuon/Playground/zig-bug/src/main.zig -lc --cache-dir /home/kuon/Playground/zig-bug/zig-cache --global-cache-dir /home/kuon/.cache/zig --name testlib -dynamic --enable-cache 
error: the following build command failed with exit code 6:
/home/kuon/Playground/zig-bug/zig-cache/o/9e2f65e31bd0e49cb1973579ed662e04/build /usr/bin/zig /home/kuon/Playground/zig-bug /home/kuon/Playground/zig-bug/zig-cache /home/kuon/.cache/zig lib

Expected Behavior

Code should compile.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorfrontendTokenization, parsing, AstGen, Sema, and Liveness.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions