getty-zig / getty

A (de)serialization framework for Zig
https://getty.so
MIT License
200 stars 13 forks source link

Inferred error sets in required method implementations crashes stage2 compiler #39

Open ibokuri opened 2 years ago

ibokuri commented 2 years ago

Description

On zig master (first seen in 0.10.0-dev.3978+4fd4c733d), stage2 compilations for some programs implementing getty.Serializer (and getty.Deserializer probably) are ~going into an infinite loop and running forever~ crashing.

The problem seems to occur when a method implementation is provided for a required method that contains an anytype parameter (e.g., serializeFloat, serializeInt). This causes the ~infinite loop~ crash. Providing implementations for methods like serializeBool or serializeNull still works completely fine.

How to Reproduce the Bug

Works

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

const Serializer = struct {
    pub usingnamespace getty.Serializer(
        @This(),
        Ok,
        Error,
        null,
        null,
        null,
        null,
        null,
        .{
            .serializeBool = serializeBool,
        },
    );

    const Ok = void;
    const Error = getty.ser.Error || error{Foobar};

    fn serializeBool(_: @This(), value: bool) !Ok {
        std.debug.print("{}\n", .{value});
    }
};

pub fn main() anyerror!void {
    var s = Serializer{};
    const serializer = s.serializer();

    try getty.serialize(null, true, serializer);
}

Doesn't Work

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

const Serializer = struct {
    pub usingnamespace getty.Serializer(
        @This(),
        Ok,
        Error,
        null,
        null,
        null,
        null,
        null,
        .{
            .serializeInt = serializeInt,
        },
    );

    const Ok = void;
    const Error = getty.ser.Error || error{Foobar};

    fn serializeInt(_: @This(), value: anytype) !Ok {
        std.debug.print("{}\n", .{value});
    }
};

pub fn main() anyerror!void {
    var s = Serializer{};
    const serializer = s.serializer();

    try getty.serialize(null, 123, serializer);
}
$ zig build run
zig build-exe test Debug native: error: thread 431519 panic: attempt to unwrap error
Unable to dump stack trace: debug info stripped

zig build-exe test Debug native: error: the following command terminated unexpectedly:
/Users/jason/.asdf/installs/zig/master/zig build-exe /Users/jason/Projects/Personal/test/src/main.zig --cache-dir /Users/jason/Projects/Personal/test/zig-cache --global-cache-dir /Users/jason/.cache/zig --name test --mod getty::/Users/jason/.cache/zig/p/1220c649e62d6bb0e07ac6b02711f76254f1dd1875859ad075873d248fb820f68d66/src/getty.zig --deps getty --listen=-
Build Summary: 0/5 steps succeeded; 1 failed (disable with -fno-summary)
run transitive failure
└─ run test transitive failure
   ├─ zig build-exe test Debug native failure
   └─ install transitive failure
      └─ install test transitive failure
         └─ zig build-exe test Debug native (reused)
error: the following build command failed with exit code 1:
/Users/jason/Projects/Personal/test/zig-cache/o/ee1be17a562f060aa4ae0c496b5dcfcc/build /Users/jason/.asdf/installs/zig/master/zig /Users/jason/Projects/Personal/test /Users/jason/Projects/Personal/test/zig-cache /Users/jason/.cache/zig run

Additional Context

Compiling with stage1 fixes the problem. So if you need a workaround for now, the following should work for you:

zig build -fstage1 run
ibokuri commented 2 years ago

The problem is apparently inferred error sets. I guess you can't use them anymore when implementing methods that have anytype parameters?

Making the error set explicit fixes this issue.

ibokuri commented 2 years ago

Relevant issue in the ziglang repo: https://github.com/ziglang/zig/issues/12806