Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler crash with empty slice in comptime generic #19888

Open
dweiller opened this issue May 7, 2024 · 0 comments
Open

Compiler crash with empty slice in comptime generic #19888

dweiller opened this issue May 7, 2024 · 0 comments
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Milestone

Comments

@dweiller
Copy link
Contributor

dweiller commented May 7, 2024

Zig Version

0.12.0 and 0.13.0-dev.46+3648d7df1

Steps to Reproduce and Observed Behavior

I haven't yet been able to make a minimal repro, but setting up a project with the following reproduces it.

build.zig.zon:

.{
    .name = "zig-bug",
    .version = "0.0.0",

    .dependencies = .{
        .zli = .{
            .url = "https://github.com/dweiller/zli/archive/cbb288b2129ab5ec8181d55cc40dd02371ef5d2b.tar.gz",
            .hash = "1220d7b865aa88f0f98dd85e3317006aff163fb9c7485d50a326d90b5b6b85c763fd",
        },
    },

    .paths = .{""},
}

build.zig:

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "zig-bug",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    exe.root_module.addImport("zli", b.dependency("zli", .{}).module("zli"));

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

src/main.zig:

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

    const parse_result = try Cli.parse(allocator);

    switch (parse_result) {
        .ok => |params| _ = params,
        .err => |err| {
            err.renderToStdErr();
            std.process.exit(1);
        },
    }
}

const arg_spec = [_]zli.Arg{};

const version: std.SemanticVersion = .{
    .major = 0,
    .minor = 0,
    .patch = 0,
};

const Cli = zli.CliCommand("buggy", version, .{ .parameters = &arg_spec });

const zli = @import("zli");
const std = @import("std");

This diff avoids the crash:

- const Cli = zli.CliCommand("buggy", version, .{ .parameters = &arg_spec });
+ const Cli = zli.CliCommand("buggy", version, .{});

(note that the default values of the .parameters field is an empty slice).

I have bisected the crash to commit d0e74ff from #19630.

A debug build of the compiler reports:

error: thread 26925 panic: reached unreachable code
Analyzing /zig-global-cache/zig/p/1220d7b865aa88f0f98dd85e3317006aff163fb9c7485d50a326d90b5b6b85c763fd/src/root.zig: root.zig:CliCommand
      %31 = dbg_stmt(6, 5)
      %32 = decl_val("checkNameClash") token_offset:15:5 to :15:19
      %33 = dbg_stmt(6, 19)
      %34 = call(nodiscard .auto, %32, [
        {
          %35 = dbg_stmt(6, 27)
          %36 = field_val(%30, "parameters") node_offset:15:20 to :15:38
          %37 = break_inline(%34, %36)
        },
        {
          %38 = dbg_stmt(6, 47)
          %39 = field_val(%30, "include_help") node_offset:15:40 to :15:60
          %40 = break_inline(%34, %39)
        },
        {
          %41 = dbg_stmt(6, 69)
          %42 = field_val(%30, "include_version") node_offset:15:62 to :15:85
          %43 = break_inline(%34, %42)
        },
      ]) node_offset:15:5 to :15:86
      %44 = dbg_stmt(8, 5)
    > %45 = extended(struct_decl(hash(2f03488edf70f049e11a99171a65c4a6) func, { %30, %23, %27 }, auto, {
        %46 = declaration('args' line(+8) hash(1d2945674f7572f65a83b8147c0c5e20) value={%47..%59}) node_offset:18:9 to :18:14
        %60 = declaration(pub 'ParsedResult' line(+13) hash(36ef7bcac61577fd88901246e9dff81a) value={%61..%67}) node_offset:23:9 to :23:65
        %68 = declaration(pub 'Params' line(+14) hash(3625003312157a5b49ab3cbbe721ab7a) value={%69..%71}) node_offset:24:9 to :24:47
        %72 = declaration('longest_arg_name' line(+16) hash(b2c32eeafb79828b1d4aae9055886a50) value={%73, %109}) node_offset:26:9 to :26:14
        %110 = declaration(pub 'parse' line(+27) hash(9cf3f5dd5feb9c07656303cc5ab34951) value={%113..%159}) node_offset:37:9 to :37:72
        %160 = declaration(pub 'parseOrExit' line(+34) hash(51efb330960d110fab034c2668a55eab) value={%163..%230}) node_offset:44:9 to :44:74
        %231 = declaration(pub 'parseWithArgs' line(+44) hash(c7b05011c33bc66be7e91c91c1c51af1) value={%234..%523}) node_offset:54:9 to :54:15
      }, {}, {}) node_offset:17:12 to :17:18
      %524 = restore_err_ret_index_unconditional(.none) node_offset:17:5 to :17:11
      %525 = dbg_stmt(8, 5)
      %526 = ret_node(%45) node_offset:17:5 to :17:11
    For full context, use the command
      zig ast-check -t /zig-global-cache/zig/p/1220d7b865aa88f0f98dd85e3317006aff163fb9c7485d50a326d90b5b6b85c763fd/src/root.zig

  in src/main.zig: main.zig:Cli
    > %85 = field_call(.compile_time, %83, "CliCommand", [
        {%86, %87},
        {%88, %89},
        {%90..%95},
      ]) node_offset:25:13 to :25:75
  in src/main.zig: main.zig:main
    > %29 = decl_ref("Cli") token_offset:6:30 to :6:33
  in /path/to/zig/lib/std/start.zig: start.zig:callMain
    > %1824 = is_non_err(%1823) 
  in /path/to/zig/lib/std/start.zig: start.zig:callMain
    > %1826 = block({%1821..%1825}) 
  in /path/to/zig/lib/std/start.zig: start.zig:callMain
    > %1772 = switch_block(%1770,
        else => {%1915, %1918},
        %1773 => {%1774..%1778},
        %1779 => {%1780..%1788},
        by_val %1789 => {%1790..%1818},
        %1819 => {%1820..%1914}) 
  in /path/to/zig/lib/std/start.zig: start.zig:callMainWithArgs
    > %1577 = call(.auto, %1575, []) 
  in /path/to/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
    > %1414 = call(.auto, %1412, [
        {%1415},
        {%1416},
        {%1417},
      ]) 
  in /path/to/zig/lib/std/start.zig: start.zig:posixCallMainAndExit
    > %1411 = field_call(nodiscard .auto, %1409, "exit", [
        {%1412..%1418},
      ]) 

/path/to/zig/src/type.zig:1039:35: 0x5ff28c6 in abiAlignmentAdvanced (zig)
                        .eager => unreachable, // struct alignment not resolved
                                  ^
/path/to/zig/src/type.zig:904:84: 0x5ff0789 in abiAlignmentAdvanced (zig)
                    return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat);
                                                                                   ^
/path/to/zig/src/type.zig:851:40: 0x5ff3a49 in abiAlignment (zig)
        return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
                                       ^
/path/to/zig/src/Module.zig:655:72: 0x66e9d36 in declPtrType (zig)
                .alignment = if (decl.alignment == decl_ty.abiAlignment(zcu))
                                                                       ^
/path/to/zig/src/Value.zig:4003:66: 0x66e9fd4 in ptrType (zig)
            inline .eu_payload_ptr, .opt_payload_ptr, .field_ptr, .elem_ptr => |x| x.result_ptr_ty,
                                                                 ^
/path/to/zig/src/Value.zig:4141:68: 0x66ebb1e in pointerDerivationAdvanced (zig)
    if (need_child.comptimeOnly(zcu)) {
                                                                   ^
/path/to/zig/src/print_value.zig:288:61: 0x7ef84dd in printPtr__anon_132272 (zig)
    try printPtrDerivation(derivation, writer, level, zcu, opt_sema);
                                                            ^
/path/to/zig/src/print_value.zig:130:25: 0x7c1f101 in print__anon_127410 (zig)
            try writer.writeAll("[0..");
                        ^
/path/to/zig/src/print_value.zig:205:26: 0x7ef8fbb in printAggregate__anon_132273 (zig)
            }
                         ^
/path/to/zig/src/print_value.zig:155:53: 0x7c1f686 in print__anon_127410 (zig)
        .un => |un| {
                                                    ^
/path/to/zig/src/print_value.zig:32:17: 0x7c1d3ea in format__anon_127409 (zig)
        error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
                ^
/path/to/zig/lib/std/fmt.zig:1480:26: 0x76df5e0 in format__anon_119546 (zig)
            try format_fn(self.data, fmt, options, writer);
                         ^
/path/to/zig/lib/std/fmt.zig:494:32: 0x71d26f2 in formatType__anon_111404 (zig)
        return try value.format(actual_fmt, options, writer);
                               ^
/path/to/zig/lib/std/fmt.zig:185:23: 0x74b62e0 in format__anon_116429 (zig)
        try formatType(
                      ^
/path/to/zig/lib/std/io/Writer.zig:23:26: 0x6fb9f30 in print__anon_103294 (zig)
    return std.fmt.format(self, format, args);
                         ^
/path/to/zig/lib/std/io.zig:324:47: 0x6fb8a86 in createAnonymousDeclTypeNamed (zig)
            return @errorCast(self.any().print(format, args));
                                              ^
/path/to/zig/src/Sema.zig:2827:65: 0x6af54be in zirStructDecl (zig)
    const new_decl_index = try sema.createAnonymousDeclTypeNamed(
                                                                ^
/path/to/zig/src/Sema.zig:1215:66: 0x6580b6f in analyzeBodyInner (zig)
                    .struct_decl        => try sema.zirStructDecl(        block, extended, inst),
                                                                 ^
/path/to/zig/src/Sema.zig:892:26: 0x6578921 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/path/to/zig/src/Sema.zig:7922:35: 0x6beb7ef in analyzeCall (zig)
                // a reference to `comptime_allocs` so is not stable across instances of `Sema`.
                                  ^
/path/to/zig/src/Sema.zig:7125:43: 0x6a80c0e in zirCall__anon_93540 (zig)

                                          ^
/path/to/zig/src/Sema.zig:1015:62: 0x6579d83 in analyzeBodyInner (zig)
            .field_call                   => try sema.zirCall(block, inst, .field),
                                                             ^
/path/to/zig/src/Sema.zig:910:30: 0x62ad5c7 in analyzeInlineBody (zig)
    if (sema.analyzeBodyInner(block, body)) |_| {
                             ^
/path/to/zig/src/Sema.zig:936:39: 0x600918e in resolveInlineBody (zig)
    return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value;
                                      ^
/path/to/zig/src/Module.zig:3650:50: 0x600526d in semaDecl (zig)
    const result_ref = try sema.resolveInlineBody(&block_scope, decl_bodies.value_body, decl_inst);
                                                 ^
/path/to/zig/src/Module.zig:3015:32: 0x5de17f1 in ensureDeclAnalyzed (zig)
        break :blk mod.semaDecl(decl_index) catch |err| switch (err) {
                               ^
/path/to/zig/src/Sema.zig:31901:27: 0x6000ff9 in ensureDeclAnalyzed (zig)
            ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
                          ^
/path/to/zig/src/Sema.zig:31946:32: 0x6bee05a in analyzeDeclRefInner (zig)
            .is_const = if (decl_val.getVariable(mod)) |variable| variable.is_const else true,
                               ^
/path/to/zig/src/Sema.zig:31937:36: 0x66a97ce in analyzeDeclRef (zig)
        .func => |func| func.owner_decl,
                                   ^
/path/to/zig/src/Sema.zig:6795:31: 0x6a831ad in zirDeclRef (zig)

                              ^
/path/to/zig/src/Sema.zig:1022:65: 0x657a24b in analyzeBodyInner (zig)
            .decl_ref                     => try sema.zirDeclRef(block, inst),
                                                                ^
/path/to/zig/src/Sema.zig:892:26: 0x6578921 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/path/to/zig/src/Module.zig:4633:23: 0x626cafb in analyzeFnBody (zig)
    sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
                      ^
/path/to/zig/src/Module.zig:3143:32: 0x5fe10d8 in ensureFuncBodyAnalyzed (zig)
    var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
                               ^
/path/to/zig/src/Sema.zig:31914:31: 0x6bf8edd in ensureFuncBodyAnalyzed (zig)
        .val = if (opt_val) |val| (try mod.getCoerced(
                              ^
/path/to/zig/src/Sema.zig:35927:40: 0x66944bd in resolveInferredErrorSet (zig)
) CompileError!void {
                                       ^
/path/to/zig/src/Sema.zig:32275:69: 0x6b3779d in analyzeIsNonErrComptimeOnly (zig)
            return .bool_true;
                                                                    ^
/path/to/zig/src/Sema.zig:32304:56: 0x6f54659 in analyzeIsNonErr (zig)
    const result = try sema.analyzePtrIsNonErrComptimeOnly(block, src, operand);
                                                       ^
/path/to/zig/src/Sema.zig:19189:32: 0x6a8e6df in zirIsNonErr (zig)

                               ^
/path/to/zig/src/Sema.zig:1056:66: 0x657b726 in analyzeBodyInner (zig)
            .is_non_err                   => try sema.zirIsNonErr(block, inst),
                                                                 ^
/path/to/zig/src/Sema.zig:6165:34: 0x6f7de7b in resolveBlockBody (zig)
                            .body_len = @intCast(child_block.instructions.items.len),
                                 ^
/path/to/zig/src/Sema.zig:6142:33: 0x6b3a62e in zirBlock (zig)
    merges: *Block.Merges,
                                ^
/path/to/zig/src/Sema.zig:1559:49: 0x658815f in analyzeBodyInner (zig)
                    break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
                                                ^
/path/to/zig/src/Sema.zig:6165:34: 0x6f7de7b in resolveBlockBody (zig)
                            .body_len = @intCast(child_block.instructions.items.len),
                                 ^
/path/to/zig/src/Sema.zig:11017:45: 0x6f74b40 in resolveProngComptime (zig)
                    return .unreachable_value;
                                            ^
/path/to/zig/src/Sema.zig:13156:48: 0x6f733a9 in resolveSwitchComptime (zig)
        var multi_i: usize = 0;
                                               ^
/path/to/zig/src/Sema.zig:12395:37: 0x6a9ea00 in zirSwitchBlock (zig)

                                    ^
/path/to/zig/src/Sema.zig:1079:69: 0x657c552 in analyzeBodyInner (zig)
            .switch_block                 => try sema.zirSwitchBlock(block, inst, false),
                                                                    ^
/path/to/zig/src/Sema.zig:892:26: 0x6578921 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/path/to/zig/src/Sema.zig:7922:35: 0x6beb7ef in analyzeCall (zig)
                // a reference to `comptime_allocs` so is not stable across instances of `Sema`.
                                  ^
/path/to/zig/src/Sema.zig:7125:43: 0x6a7f99e in zirCall__anon_93539 (zig)

                                          ^
/path/to/zig/src/Sema.zig:1014:62: 0x6579ce6 in analyzeBodyInner (zig)
            .call                         => try sema.zirCall(block, inst, .direct),
                                                             ^
/path/to/zig/src/Sema.zig:892:26: 0x6578921 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/path/to/zig/src/Sema.zig:7922:35: 0x6beb7ef in analyzeCall (zig)
                // a reference to `comptime_allocs` so is not stable across instances of `Sema`.
                                  ^
/path/to/zig/src/Sema.zig:7125:43: 0x6a7f99e in zirCall__anon_93539 (zig)

                                          ^
/path/to/zig/src/Sema.zig:1014:62: 0x6579ce6 in analyzeBodyInner (zig)
            .call                         => try sema.zirCall(block, inst, .direct),
                                                             ^
/path/to/zig/src/Sema.zig:910:30: 0x62ad5c7 in analyzeInlineBody (zig)
    if (sema.analyzeBodyInner(block, body)) |_| {
                             ^
/path/to/zig/src/Sema.zig:936:39: 0x600918e in resolveInlineBody (zig)
    return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value;
                                      ^
/path/to/zig/src/Sema.zig:7414:65: 0x715c437 in analyzeArg (zig)
        switch (param_ty.toIntern()) {
                                                                ^
/path/to/zig/src/Sema.zig:7977:49: 0x6bec57e in analyzeCall (zig)
            if (mod.intern_pool.isFuncBody(func_val.toIntern())) {
                                                ^
/path/to/zig/src/Sema.zig:7125:43: 0x6a80c0e in zirCall__anon_93540 (zig)

                                          ^
/path/to/zig/src/Sema.zig:1015:62: 0x6579d83 in analyzeBodyInner (zig)
            .field_call                   => try sema.zirCall(block, inst, .field),
                                                             ^
/path/to/zig/src/Sema.zig:892:26: 0x6578921 in analyzeFnBody (zig)
    sema.analyzeBodyInner(block, body) catch |err| switch (err) {
                         ^
/path/to/zig/src/Module.zig:4633:23: 0x626cafb in analyzeFnBody (zig)
    sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
                      ^
/path/to/zig/src/Module.zig:3143:32: 0x5fe10d8 in ensureFuncBodyAnalyzed (zig)
    var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
                               ^
/path/to/zig/src/Compilation.zig:3419:42: 0x5fdede2 in processOneJob (zig)
            module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
                                         ^
/path/to/zig/src/Compilation.zig:3359:30: 0x5e0db3a in performAllTheWork (zig)
            try processOneJob(comp, work_item, main_progress_node);
                             ^
/path/to/zig/src/Compilation.zig:2132:31: 0x5e09072 in update (zig)
    try comp.performAllTheWork(main_progress_node);
                              ^
/path/to/zig/src/main.zig:4085:36: 0x5e83f4c in serve (zig)
                    continue;
                                   ^
/path/to/zig/src/main.zig:3362:22: 0x5ea2681 in buildOutputType (zig)
    if (show_builtin) {
                     ^
/path/to/zig/src/main.zig:260:31: 0x5ceb331 in mainArgs (zig)
        return buildOutputType(gpa, arena, args, .{ .build = .Exe });
                              ^
/path/to/zig/src/main.zig:206:20: 0x5ce82c5 in main (zig)
    return mainArgs(gpa, arena, args);
                   ^
/path/to/zig/lib/std/start.zig:511:37: 0x5ce7d5e in main (zig)
            const result = root.main() catch |err| {
                                    ^
../sysdeps/nptl/libc_start_call_main.h:58:16: 0x7f10145aad8f in __libc_start_call_main (../sysdeps/x86/libc-start.c)
../csu/libc-start.c:392:3: 0x7f10145aae3f in __libc_start_main_impl (../sysdeps/x86/libc-start.c)
???:?:?: 0x5ce79a4 in ??? (???)
???:?:?: 0x0 in ??? (???)

Expected Behavior

The compiler shouldn't crash - the stack trace makes it look like it's hitting unreachable, but it also looks like the trace isn't printing quite correctly (arrows pointing to odd columns, some arrows don't have a line their pointing to etc), so not sure how much it can be trusted. The stack trace was generated by a debug build of zig version 0.12.1-dev.17+600b65282.

@dweiller dweiller added the bug Observed behavior contradicts documented or intended behavior label May 7, 2024
@Vexu Vexu added the frontend Tokenization, parsing, AstGen, Sema, and Liveness. label May 7, 2024
@Vexu Vexu added this to the 0.13.0 milestone May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Projects
None yet
Development

No branches or pull requests

2 participants