mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 15:43:06 +00:00
stage2: error set merging with tests
I had to come up with creative tests because we don't have error set type equality yet.
This commit is contained in:
parent
4b57fb5f23
commit
8b100792eb
@ -1196,7 +1196,81 @@ fn zirErrorValue(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorValue) InnerE
|
||||
fn zirMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});
|
||||
|
||||
const rhs_ty = try resolveType(mod, scope, inst.positionals.rhs);
|
||||
const lhs_ty = try resolveType(mod, scope, inst.positionals.lhs);
|
||||
if (rhs_ty.zigTypeTag() != .ErrorSet)
|
||||
return mod.fail(scope, inst.positionals.rhs.src, "expected error set type, found {}", .{rhs_ty});
|
||||
if (lhs_ty.zigTypeTag() != .ErrorSet)
|
||||
return mod.fail(scope, inst.positionals.lhs.src, "expected error set type, found {}", .{lhs_ty});
|
||||
|
||||
// anything merged with anyerror is anyerror
|
||||
if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror)
|
||||
return mod.constInst(scope, inst.base.src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.anyerror_type),
|
||||
});
|
||||
// The declarations arena will store the hashmap.
|
||||
var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
|
||||
errdefer new_decl_arena.deinit();
|
||||
|
||||
const payload = try new_decl_arena.allocator.create(Value.Payload.ErrorSet);
|
||||
payload.* = .{
|
||||
.base = .{ .tag = .error_set },
|
||||
.data = .{
|
||||
.fields = .{},
|
||||
.decl = undefined, // populated below
|
||||
},
|
||||
};
|
||||
try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, switch (rhs_ty.tag()) {
|
||||
.error_set_single => 1,
|
||||
.error_set => rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size,
|
||||
else => unreachable,
|
||||
} + switch (lhs_ty.tag()) {
|
||||
.error_set_single => 1,
|
||||
.error_set => lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size,
|
||||
else => unreachable,
|
||||
}));
|
||||
|
||||
switch (lhs_ty.tag()) {
|
||||
.error_set_single => {
|
||||
const name = lhs_ty.castTag(.error_set_single).?.data;
|
||||
const num = mod.global_error_set.get(name).?;
|
||||
payload.data.fields.putAssumeCapacity(name, num);
|
||||
},
|
||||
.error_set => {
|
||||
var multiple = lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;
|
||||
var it = multiple.iterator();
|
||||
while (it.next()) |entry| {
|
||||
payload.data.fields.putAssumeCapacity(entry.key, entry.value);
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
switch (rhs_ty.tag()) {
|
||||
.error_set_single => {
|
||||
const name = rhs_ty.castTag(.error_set_single).?.data;
|
||||
const num = mod.global_error_set.get(name).?;
|
||||
payload.data.fields.putAssumeCapacity(name, num);
|
||||
},
|
||||
.error_set => {
|
||||
var multiple = rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;
|
||||
var it = multiple.iterator();
|
||||
while (it.next()) |name| {
|
||||
const entry = try mod.getErrorValue(name.key);
|
||||
payload.data.fields.putAssumeCapacity(entry.key, entry.value);
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initPayload(&payload.base),
|
||||
});
|
||||
payload.data.decl = new_decl;
|
||||
|
||||
return mod.analyzeDeclVal(scope, inst.base.src, new_decl);
|
||||
}
|
||||
|
||||
fn zirEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
|
||||
|
||||
@ -985,7 +985,7 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
"Hello, World!\n",
|
||||
);
|
||||
try case.files.append(.{
|
||||
.src =
|
||||
.src =
|
||||
\\pub fn print() void {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
@ -1525,4 +1525,37 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
{
|
||||
var case = ctx.exe("merge error sets", linux_x64);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
\\ const E = error{ A, B, D } || error { A, B, C };
|
||||
\\ const a = E.A;
|
||||
\\ const b = E.B;
|
||||
\\ const c = E.C;
|
||||
\\ const d = E.D;
|
||||
\\ const E2 = error { X, Y } || @TypeOf(error.Z);
|
||||
\\ const x = E2.X;
|
||||
\\ const y = E2.Y;
|
||||
\\ const z = E2.Z;
|
||||
\\ assert(anyerror || error { Z } == anyerror);
|
||||
\\ exit();
|
||||
\\}
|
||||
\\fn assert(b: bool) void {
|
||||
\\ if (!b) unreachable;
|
||||
\\}
|
||||
\\fn exit() noreturn {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (231),
|
||||
\\ [arg1] "{rdi}" (0)
|
||||
\\ : "rcx", "r11", "memory"
|
||||
\\ );
|
||||
\\ unreachable;
|
||||
\\}
|
||||
,
|
||||
"",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user