Skip to content

Commit

Permalink
stage2: error_set_merged type equality
Browse files Browse the repository at this point in the history
This implements type equality for merged error types. This is done
through element-wise error set comparison. This is a bit odd since
no other error type is structurally compared (see ziglang#11022) but it appears
to be the same behavior that stage1 also expects based on tests.
  • Loading branch information
mitchellh committed Mar 10, 2022
1 parent 6e49ba7 commit 9ca2c65
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
38 changes: 22 additions & 16 deletions src/type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -567,24 +567,30 @@ pub const Type = extern union {
// TODO: revisit the language specification for how to evaluate equality
// for error set types.

if (a.tag() == .anyerror and b.tag() == .anyerror) {
return true;
}

if (a.tag() == .error_set and b.tag() == .error_set) {
return a.castTag(.error_set).?.data.owner_decl == b.castTag(.error_set).?.data.owner_decl;
}
if (a.tag() != b.tag()) return false;

return switch (a.tag()) {
.anyerror => true,
.error_set => a.castTag(.error_set).?.data.owner_decl == b.castTag(.error_set).?.data.owner_decl,
.error_set_inferred => a.castTag(.error_set_inferred).?.data == b.castTag(.error_set_inferred).?.data,
.error_set_single => blk: {
const a_data = a.castTag(.error_set_single).?.data;
const b_data = b.castTag(.error_set_single).?.data;
break :blk std.mem.eql(u8, a_data, b_data);
},
.error_set_merged => blk: {
const a_data = a.castTag(.error_set_merged).?.data;
const b_data = b.castTag(.error_set_merged).?.data;
if (a_data.count() != b_data.count()) break :blk false;
for (a_data.keys()) |name| {
if (!b_data.contains(name)) break :blk false;
}

if (a.tag() == .error_set_inferred and b.tag() == .error_set_inferred) {
return a.castTag(.error_set_inferred).?.data == b.castTag(.error_set_inferred).?.data;
}
break :blk true;
},

if (a.tag() == .error_set_single and b.tag() == .error_set_single) {
const a_data = a.castTag(.error_set_single).?.data;
const b_data = b.castTag(.error_set_single).?.data;
return std.mem.eql(u8, a_data, b_data);
}
return false;
else => false,
};
},

.@"opaque" => {
Expand Down
18 changes: 15 additions & 3 deletions test/behavior/error.zig
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,11 @@ fn intLiteral(str: []const u8) !?i64 {
}

test "nested error union function call in optional unwrap" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;

const S = struct {
const Foo = struct {
Expand Down Expand Up @@ -404,7 +408,11 @@ test "optional error set is the same size as error set" {
}

test "nested catch" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;

const S = struct {
fn entry() !void {
Expand Down Expand Up @@ -480,7 +488,11 @@ test "return result loc as peer result loc in inferred error set function" {
}

test "error payload type is correctly resolved" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;

const MyIntWrapper = struct {
const Self = @This();
Expand Down

0 comments on commit 9ca2c65

Please sign in to comment.