authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-02 23:19:22-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-03-02 23:19:22-08:00
log5bd9a6451685ad056628e312aadaf80e66a4c004
tree3a7afa14fcfdcaf4f07acca0f52e5e545e8f6708
parent4b57fb5f23aa6513ceaebe396d1faf215cf0a475
parent39957832071cd999d6abc16c91e12c4820a2a738
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7778 from g-w1/stage2-merge-errors

stage2: error set merging with tests

3 files changed, 111 insertions(+), 4 deletions(-)

src/astgen.zig+2-2
...@@ -1655,7 +1655,7 @@ fn errorSetDecl(...@@ -1655,7 +1655,7 @@ fn errorSetDecl(
1655 switch (token_tags[tok_i]) {1655 switch (token_tags[tok_i]) {
1656 .doc_comment, .comma => {},1656 .doc_comment, .comma => {},
1657 .identifier => count += 1,1657 .identifier => count += 1,
1658 .r_paren => break :count count,1658 .r_brace => break :count count,
1659 else => unreachable,1659 else => unreachable,
1660 }1660 }
1661 } else unreachable; // TODO should not need else unreachable here1661 } else unreachable; // TODO should not need else unreachable here
...@@ -1672,7 +1672,7 @@ fn errorSetDecl(...@@ -1672,7 +1672,7 @@ fn errorSetDecl(
1672 fields[field_i] = try mod.identifierTokenString(scope, tok_i);1672 fields[field_i] = try mod.identifierTokenString(scope, tok_i);
1673 field_i += 1;1673 field_i += 1;
1674 },1674 },
1675 .r_paren => break,1675 .r_brace => break,
1676 else => unreachable,1676 else => unreachable,
1677 }1677 }
1678 }1678 }
src/zir_sema.zig+75-1
...@@ -1196,7 +1196,81 @@ fn zirErrorValue(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorValue) InnerE...@@ -1196,7 +1196,81 @@ fn zirErrorValue(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorValue) InnerE
1196fn zirMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1196fn zirMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
1197 const tracy = trace(@src());1197 const tracy = trace(@src());
1198 defer tracy.end();1198 defer tracy.end();
1199 return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});1199
1200 const rhs_ty = try resolveType(mod, scope, inst.positionals.rhs);
1201 const lhs_ty = try resolveType(mod, scope, inst.positionals.lhs);
1202 if (rhs_ty.zigTypeTag() != .ErrorSet)
1203 return mod.fail(scope, inst.positionals.rhs.src, "expected error set type, found {}", .{rhs_ty});
1204 if (lhs_ty.zigTypeTag() != .ErrorSet)
1205 return mod.fail(scope, inst.positionals.lhs.src, "expected error set type, found {}", .{lhs_ty});
1206
1207 // anything merged with anyerror is anyerror
1208 if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror)
1209 return mod.constInst(scope, inst.base.src, .{
1210 .ty = Type.initTag(.type),
1211 .val = Value.initTag(.anyerror_type),
1212 });
1213 // The declarations arena will store the hashmap.
1214 var new_decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
1215 errdefer new_decl_arena.deinit();
1216
1217 const payload = try new_decl_arena.allocator.create(Value.Payload.ErrorSet);
1218 payload.* = .{
1219 .base = .{ .tag = .error_set },
1220 .data = .{
1221 .fields = .{},
1222 .decl = undefined, // populated below
1223 },
1224 };
1225 try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, switch (rhs_ty.tag()) {
1226 .error_set_single => 1,
1227 .error_set => rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size,
1228 else => unreachable,
1229 } + switch (lhs_ty.tag()) {
1230 .error_set_single => 1,
1231 .error_set => lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size,
1232 else => unreachable,
1233 }));
1234
1235 switch (lhs_ty.tag()) {
1236 .error_set_single => {
1237 const name = lhs_ty.castTag(.error_set_single).?.data;
1238 const num = mod.global_error_set.get(name).?;
1239 payload.data.fields.putAssumeCapacity(name, num);
1240 },
1241 .error_set => {
1242 var multiple = lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;
1243 var it = multiple.iterator();
1244 while (it.next()) |entry| {
1245 payload.data.fields.putAssumeCapacity(entry.key, entry.value);
1246 }
1247 },
1248 else => unreachable,
1249 }
1250
1251 switch (rhs_ty.tag()) {
1252 .error_set_single => {
1253 const name = rhs_ty.castTag(.error_set_single).?.data;
1254 const num = mod.global_error_set.get(name).?;
1255 payload.data.fields.putAssumeCapacity(name, num);
1256 },
1257 .error_set => {
1258 var multiple = rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;
1259 var it = multiple.iterator();
1260 while (it.next()) |entry| {
1261 payload.data.fields.putAssumeCapacity(entry.key, entry.value);
1262 }
1263 },
1264 else => unreachable,
1265 }
1266 // TODO create name in format "error:line:column"
1267 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
1268 .ty = Type.initTag(.type),
1269 .val = Value.initPayload(&payload.base),
1270 });
1271 payload.data.decl = new_decl;
1272
1273 return mod.analyzeDeclVal(scope, inst.base.src, new_decl);
1200}1274}
12011275
1202fn zirEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {1276fn zirEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
test/stage2/test.zig+34-1
...@@ -985,7 +985,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -985,7 +985,7 @@ pub fn addCases(ctx: *TestContext) !void {
985 "Hello, World!\n",985 "Hello, World!\n",
986 );986 );
987 try case.files.append(.{987 try case.files.append(.{
988 .src =988 .src =
989 \\pub fn print() void {989 \\pub fn print() void {
990 \\ asm volatile ("syscall"990 \\ asm volatile ("syscall"
991 \\ :991 \\ :
...@@ -1525,4 +1525,37 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1525,4 +1525,37 @@ pub fn addCases(ctx: *TestContext) !void {
1525 \\}1525 \\}
1526 , "");1526 , "");
1527 }1527 }
1528 {
1529 var case = ctx.exe("merge error sets", linux_x64);
1530
1531 case.addCompareOutput(
1532 \\export fn _start() noreturn {
1533 \\ const E = error{ A, B, D } || error { A, B, C };
1534 \\ const a = E.A;
1535 \\ const b = E.B;
1536 \\ const c = E.C;
1537 \\ const d = E.D;
1538 \\ const E2 = error { X, Y } || @TypeOf(error.Z);
1539 \\ const x = E2.X;
1540 \\ const y = E2.Y;
1541 \\ const z = E2.Z;
1542 \\ assert(anyerror || error { Z } == anyerror);
1543 \\ exit();
1544 \\}
1545 \\fn assert(b: bool) void {
1546 \\ if (!b) unreachable;
1547 \\}
1548 \\fn exit() noreturn {
1549 \\ asm volatile ("syscall"
1550 \\ :
1551 \\ : [number] "{rax}" (231),
1552 \\ [arg1] "{rdi}" (0)
1553 \\ : "rcx", "r11", "memory"
1554 \\ );
1555 \\ unreachable;
1556 \\}
1557 ,
1558 "",
1559 );
1560 }
1528}1561}