I get this strange error where zig thinks I haven’t handled an error case, but if I attempt to use try on it, then the compiler complains that I’m using try on a non error value
Any help would be appreciated
I reduced my code down to a minimal example:
const std = @import("std");
/// A combinator parser / functional parser.
pub fn Parser(comptime T: type) type {
return fn ([]u8) ParseError!struct { T, []u8 };
}
pub const ParseError = error{
/// The parser could succeed given more input, but ran out.
Incomplete,
/// An unrecoverable failure has occurred.
Panic,
};
/// Matches a string of one or more characters.
pub fn tag(comptime pattern: []const u8) Parser([]const u8) {
const s = struct {
fn invoke(rest: []u8) ParseError!struct { []const u8, []u8 } {
if (rest.len < pattern.len) {
return ParseError.Incomplete;
} else {
for (pattern, 0..) |char, j| {
if (rest[j] != char) {
return ParseError.Panic;
}
} else {
return .{ pattern, rest[pattern.len..] };
}
}
}
};
return s.invoke;
}
/// Match either of two given parsers
// zig fmt: off
pub fn either(
T: type,
left: Parser(T),
right: Parser(T)
) Parser(T) {
// zig fmt: on
const s = struct {
pub fn invoke(rest: []u8) ParseError!struct { T, []u8 } {
if (left(rest)) |result| {
return result;
} else |err| {
switch (err) {
ParseError.Incomplete => return err,
ParseError.Panic => return right(rest),
}
}
}
};
return s.invoke;
}
test "either" {
// Should match any string of either "foo" or "bar"
const parse_foobar = either([]const u8, tag("foo"), tag("bar"));
const foo, var rest = try parse_foobar(@constCast("foo"));
// error: error union is ignored
std.testing.expectEqual(rest.len, 0);
// error: expected error union type, found 'usize'
// std.testing.expectEqual(try rest.len, 0);
std.testing.expectEqual(foo, "foo");
const bar, rest = try parse_foobar(@constCast("bar"));
std.testing.expectEqual(rest.len, 0);
std.testing.expectEqual(bar, "bar");
}