authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-28 19:38:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-28 19:40:21-07:00
log8f469c11275e60f5f1a8ae08fc7596ba366eda16
tree0d6d8894eeb6f6ce42d7994d92c5df278ba436d9
parent0005b346375f1fbe7bc42c22d658e3218bbd599d

stage2: fix error sets


7 files changed, 217 insertions(+), 236 deletions(-)

src/AstGen.zig+54-46
...@@ -197,7 +197,7 @@ pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerErro...@@ -197,7 +197,7 @@ pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerErro
197}197}
198198
199fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {199fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
200 const tree = scope.tree();200 const tree = gz.tree();
201 const node_tags = tree.nodes.items(.tag);201 const node_tags = tree.nodes.items(.tag);
202 const main_tokens = tree.nodes.items(.main_token);202 const main_tokens = tree.nodes.items(.main_token);
203 switch (node_tags[node]) {203 switch (node_tags[node]) {
...@@ -392,7 +392,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins...@@ -392,7 +392,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins
392/// it must otherwise not be used.392/// it must otherwise not be used.
393pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {393pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {
394 const mod = gz.astgen.mod;394 const mod = gz.astgen.mod;
395 const tree = scope.tree();395 const tree = gz.tree();
396 const main_tokens = tree.nodes.items(.main_token);396 const main_tokens = tree.nodes.items(.main_token);
397 const token_tags = tree.tokens.items(.tag);397 const token_tags = tree.tokens.items(.tag);
398 const node_datas = tree.nodes.items(.data);398 const node_datas = tree.nodes.items(.data);
...@@ -925,7 +925,7 @@ pub fn blockExpr(...@@ -925,7 +925,7 @@ pub fn blockExpr(
925 const tracy = trace(@src());925 const tracy = trace(@src());
926 defer tracy.end();926 defer tracy.end();
927927
928 const tree = scope.tree();928 const tree = gz.tree();
929 const main_tokens = tree.nodes.items(.main_token);929 const main_tokens = tree.nodes.items(.main_token);
930 const token_tags = tree.tokens.items(.tag);930 const token_tags = tree.tokens.items(.tag);
931931
...@@ -996,7 +996,7 @@ fn labeledBlockExpr(...@@ -996,7 +996,7 @@ fn labeledBlockExpr(
996 assert(zir_tag == .block);996 assert(zir_tag == .block);
997997
998 const mod = gz.astgen.mod;998 const mod = gz.astgen.mod;
999 const tree = parent_scope.tree();999 const tree = gz.tree();
1000 const main_tokens = tree.nodes.items(.main_token);1000 const main_tokens = tree.nodes.items(.main_token);
1001 const token_tags = tree.tokens.items(.tag);1001 const token_tags = tree.tokens.items(.tag);
10021002
...@@ -1074,7 +1074,7 @@ fn blockExprStmts(...@@ -1074,7 +1074,7 @@ fn blockExprStmts(
1074 node: ast.Node.Index,1074 node: ast.Node.Index,
1075 statements: []const ast.Node.Index,1075 statements: []const ast.Node.Index,
1076) !void {1076) !void {
1077 const tree = parent_scope.tree();1077 const tree = gz.tree();
1078 const main_tokens = tree.nodes.items(.main_token);1078 const main_tokens = tree.nodes.items(.main_token);
1079 const node_tags = tree.nodes.items(.tag);1079 const node_tags = tree.nodes.items(.tag);
10801080
...@@ -1235,7 +1235,6 @@ fn blockExprStmts(...@@ -1235,7 +1235,6 @@ fn blockExprStmts(
1235 .merge_error_sets,1235 .merge_error_sets,
1236 .error_union_type,1236 .error_union_type,
1237 .bit_not,1237 .bit_not,
1238 .error_set,
1239 .error_value,1238 .error_value,
1240 .error_to_int,1239 .error_to_int,
1241 .int_to_error,1240 .int_to_error,
...@@ -1305,7 +1304,7 @@ fn varDecl(...@@ -1305,7 +1304,7 @@ fn varDecl(
1305 return mod.failNode(scope, var_decl.ast.align_node, "TODO implement alignment on locals", .{});1304 return mod.failNode(scope, var_decl.ast.align_node, "TODO implement alignment on locals", .{});
1306 }1305 }
1307 const astgen = gz.astgen;1306 const astgen = gz.astgen;
1308 const tree = scope.tree();1307 const tree = gz.tree();
1309 const token_tags = tree.tokens.items(.tag);1308 const token_tags = tree.tokens.items(.tag);
13101309
1311 const name_token = var_decl.ast.mut_token + 1;1310 const name_token = var_decl.ast.mut_token + 1;
...@@ -1365,7 +1364,7 @@ fn varDecl(...@@ -1365,7 +1364,7 @@ fn varDecl(
1365 // Depending on the type of AST the initialization expression is, we may need an lvalue1364 // Depending on the type of AST the initialization expression is, we may need an lvalue
1366 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as1365 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
1367 // the variable, no memory location needed.1366 // the variable, no memory location needed.
1368 if (!nodeMayNeedMemoryLocation(scope, var_decl.ast.init_node)) {1367 if (!nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node)) {
1369 const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{1368 const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{
1370 .ty = try typeExpr(gz, scope, var_decl.ast.type_node),1369 .ty = try typeExpr(gz, scope, var_decl.ast.type_node),
1371 } else .none;1370 } else .none;
...@@ -1502,7 +1501,7 @@ fn varDecl(...@@ -1502,7 +1501,7 @@ fn varDecl(
1502}1501}
15031502
1504fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {1503fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
1505 const tree = scope.tree();1504 const tree = gz.tree();
1506 const node_datas = tree.nodes.items(.data);1505 const node_datas = tree.nodes.items(.data);
1507 const main_tokens = tree.nodes.items(.main_token);1506 const main_tokens = tree.nodes.items(.main_token);
1508 const node_tags = tree.nodes.items(.tag);1507 const node_tags = tree.nodes.items(.tag);
...@@ -1527,7 +1526,7 @@ fn assignOp(...@@ -1527,7 +1526,7 @@ fn assignOp(
1527 infix_node: ast.Node.Index,1526 infix_node: ast.Node.Index,
1528 op_inst_tag: zir.Inst.Tag,1527 op_inst_tag: zir.Inst.Tag,
1529) InnerError!void {1528) InnerError!void {
1530 const tree = scope.tree();1529 const tree = gz.tree();
1531 const node_datas = tree.nodes.items(.data);1530 const node_datas = tree.nodes.items(.data);
15321531
1533 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);1532 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
...@@ -1543,7 +1542,7 @@ fn assignOp(...@@ -1543,7 +1542,7 @@ fn assignOp(
1543}1542}
15441543
1545fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {1544fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {
1546 const tree = scope.tree();1545 const tree = gz.tree();
1547 const node_datas = tree.nodes.items(.data);1546 const node_datas = tree.nodes.items(.data);
15481547
1549 const operand = try expr(gz, scope, .{ .ty = .bool_type }, node_datas[node].lhs);1548 const operand = try expr(gz, scope, .{ .ty = .bool_type }, node_datas[node].lhs);
...@@ -1552,7 +1551,7 @@ fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inne...@@ -1552,7 +1551,7 @@ fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inne
1552}1551}
15531552
1554fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {1553fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {
1555 const tree = scope.tree();1554 const tree = gz.tree();
1556 const node_datas = tree.nodes.items(.data);1555 const node_datas = tree.nodes.items(.data);
15571556
1558 const operand = try expr(gz, scope, .none, node_datas[node].lhs);1557 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
...@@ -1567,7 +1566,7 @@ fn negation(...@@ -1567,7 +1566,7 @@ fn negation(
1567 node: ast.Node.Index,1566 node: ast.Node.Index,
1568 tag: zir.Inst.Tag,1567 tag: zir.Inst.Tag,
1569) InnerError!zir.Inst.Ref {1568) InnerError!zir.Inst.Ref {
1570 const tree = scope.tree();1569 const tree = gz.tree();
1571 const node_datas = tree.nodes.items(.data);1570 const node_datas = tree.nodes.items(.data);
15721571
1573 const operand = try expr(gz, scope, .none, node_datas[node].lhs);1572 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
...@@ -1582,7 +1581,7 @@ fn ptrType(...@@ -1582,7 +1581,7 @@ fn ptrType(
1582 node: ast.Node.Index,1581 node: ast.Node.Index,
1583 ptr_info: ast.full.PtrType,1582 ptr_info: ast.full.PtrType,
1584) InnerError!zir.Inst.Ref {1583) InnerError!zir.Inst.Ref {
1585 const tree = scope.tree();1584 const tree = gz.tree();
15861585
1587 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);1586 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
15881587
...@@ -1664,7 +1663,7 @@ fn ptrType(...@@ -1664,7 +1663,7 @@ fn ptrType(
1664}1663}
16651664
1666fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {1665fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {
1667 const tree = scope.tree();1666 const tree = gz.tree();
1668 const node_datas = tree.nodes.items(.data);1667 const node_datas = tree.nodes.items(.data);
16691668
1670 // TODO check for [_]T1669 // TODO check for [_]T
...@@ -1676,7 +1675,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !z...@@ -1676,7 +1675,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !z
1676}1675}
16771676
1678fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {1677fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {
1679 const tree = scope.tree();1678 const tree = gz.tree();
1680 const node_datas = tree.nodes.items(.data);1679 const node_datas = tree.nodes.items(.data);
1681 const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);1680 const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);
16821681
...@@ -1704,10 +1703,11 @@ fn errorSetDecl(...@@ -1704,10 +1703,11 @@ fn errorSetDecl(
1704 rl: ResultLoc,1703 rl: ResultLoc,
1705 node: ast.Node.Index,1704 node: ast.Node.Index,
1706) InnerError!zir.Inst.Ref {1705) InnerError!zir.Inst.Ref {
1707 if (true) @panic("TODO update for zir-memory-layout branch");1706 const mod = gz.astgen.mod;
1708 const tree = gz.tree();1707 const tree = gz.tree();
1709 const main_tokens = tree.nodes.items(.main_token);1708 const main_tokens = tree.nodes.items(.main_token);
1710 const token_tags = tree.tokens.items(.tag);1709 const token_tags = tree.tokens.items(.tag);
1710 const arena = gz.astgen.arena;
17111711
1712 // Count how many fields there are.1712 // Count how many fields there are.
1713 const error_token = main_tokens[node];1713 const error_token = main_tokens[node];
...@@ -1724,7 +1724,7 @@ fn errorSetDecl(...@@ -1724,7 +1724,7 @@ fn errorSetDecl(
1724 } else unreachable; // TODO should not need else unreachable here1724 } else unreachable; // TODO should not need else unreachable here
1725 };1725 };
17261726
1727 const fields = try scope.arena().alloc([]const u8, count);1727 const fields = try arena.alloc([]const u8, count);
1728 {1728 {
1729 var tok_i = error_token + 2;1729 var tok_i = error_token + 2;
1730 var field_i: usize = 0;1730 var field_i: usize = 0;
...@@ -1740,8 +1740,21 @@ fn errorSetDecl(...@@ -1740,8 +1740,21 @@ fn errorSetDecl(
1740 }1740 }
1741 }1741 }
1742 }1742 }
1743 const result = try addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{});1743 const error_set = try arena.create(Module.ErrorSet);
1744 return rvalue(gz, scope, rl, result);1744 error_set.* = .{
1745 .owner_decl = gz.astgen.decl,
1746 .node_offset = gz.astgen.decl.nodeIndexToRelative(node),
1747 .names_ptr = fields.ptr,
1748 .names_len = @intCast(u32, fields.len),
1749 };
1750 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
1751 const typed_value = try arena.create(TypedValue);
1752 typed_value.* = .{
1753 .ty = Type.initTag(.type),
1754 .val = try Value.Tag.ty.create(arena, error_set_ty),
1755 };
1756 const result = try gz.addConst(typed_value);
1757 return rvalue(gz, scope, rl, result, node);
1745}1758}
17461759
1747fn orelseCatchExpr(1760fn orelseCatchExpr(
...@@ -2518,13 +2531,12 @@ fn getRangeNode(...@@ -2518,13 +2531,12 @@ fn getRangeNode(
2518}2531}
25192532
2520fn switchExpr(2533fn switchExpr(
2521 gz: *GenZir,2534 parent_gz: *GenZir,
2522 scope: *Scope,2535 scope: *Scope,
2523 rl: ResultLoc,2536 rl: ResultLoc,
2524 switch_node: ast.Node.Index,2537 switch_node: ast.Node.Index,
2525) InnerError!zir.Inst.Ref {2538) InnerError!zir.Inst.Ref {
2526 if (true) @panic("TODO update for zir-memory-layout");2539 if (true) @panic("TODO update for zir-memory-layout");
2527 const parent_gz = scope.getGenZir();
2528 const tree = parent_gz.tree();2540 const tree = parent_gz.tree();
2529 const node_datas = tree.nodes.items(.data);2541 const node_datas = tree.nodes.items(.data);
2530 const main_tokens = tree.nodes.items(.main_token);2542 const main_tokens = tree.nodes.items(.main_token);
...@@ -2541,7 +2553,7 @@ fn switchExpr(...@@ -2541,7 +2553,7 @@ fn switchExpr(
2541 var block_scope: GenZir = .{2553 var block_scope: GenZir = .{
2542 .parent = scope,2554 .parent = scope,
2543 .decl = scope.ownerDecl().?,2555 .decl = scope.ownerDecl().?,
2544 .arena = scope.arena(),2556 .arena = parent_gz.astgen.arena,
2545 .force_comptime = parent_gz.force_comptime,2557 .force_comptime = parent_gz.force_comptime,
2546 .instructions = .{},2558 .instructions = .{},
2547 };2559 };
...@@ -2727,7 +2739,7 @@ fn switchExpr(...@@ -2727,7 +2739,7 @@ fn switchExpr(
27272739
2728 cases[case_index] = .{2740 cases[case_index] = .{
2729 .item = item,2741 .item = item,
2730 .body = .{ .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items) },2742 .body = .{ .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items) },
2731 };2743 };
2732 case_index += 1;2744 case_index += 1;
2733 continue;2745 continue;
...@@ -2774,14 +2786,14 @@ fn switchExpr(...@@ -2774,14 +2786,14 @@ fn switchExpr(
2774 .else_body = undefined, // populated below2786 .else_body = undefined, // populated below
2775 }, .{});2787 }, .{});
2776 const cond_block = try addZIRInstBlock(mod, &else_scope.base, case_src, .block, .{2788 const cond_block = try addZIRInstBlock(mod, &else_scope.base, case_src, .block, .{
2777 .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items),2789 .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items),
2778 });2790 });
27792791
2780 // reset cond_scope for then_body2792 // reset cond_scope for then_body
2781 case_scope.instructions.items.len = 0;2793 case_scope.instructions.items.len = 0;
2782 try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target);2794 try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target);
2783 condbr.positionals.then_body = .{2795 condbr.positionals.then_body = .{
2784 .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items),2796 .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items),
2785 };2797 };
27862798
2787 // reset cond_scope for else_body2799 // reset cond_scope for else_body
...@@ -2790,7 +2802,7 @@ fn switchExpr(...@@ -2790,7 +2802,7 @@ fn switchExpr(
2790 .block = cond_block,2802 .block = cond_block,
2791 }, .{});2803 }, .{});
2792 condbr.positionals.else_body = .{2804 condbr.positionals.else_body = .{
2793 .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items),2805 .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items),
2794 };2806 };
2795 }2807 }
27962808
...@@ -2816,7 +2828,7 @@ fn switchCaseExpr(...@@ -2816,7 +2828,7 @@ fn switchCaseExpr(
2816 case: ast.full.SwitchCase,2828 case: ast.full.SwitchCase,
2817 target: zir.Inst.Ref,2829 target: zir.Inst.Ref,
2818) !void {2830) !void {
2819 const tree = scope.tree();2831 const tree = gz.tree();
2820 const node_datas = tree.nodes.items(.data);2832 const node_datas = tree.nodes.items(.data);
2821 const main_tokens = tree.nodes.items(.main_token);2833 const main_tokens = tree.nodes.items(.main_token);
2822 const token_tags = tree.tokens.items(.tag);2834 const token_tags = tree.tokens.items(.tag);
...@@ -2849,13 +2861,13 @@ fn switchCaseExpr(...@@ -2849,13 +2861,13 @@ fn switchCaseExpr(
2849}2861}
28502862
2851fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {2863fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
2852 const tree = scope.tree();2864 const tree = gz.tree();
2853 const node_datas = tree.nodes.items(.data);2865 const node_datas = tree.nodes.items(.data);
2854 const main_tokens = tree.nodes.items(.main_token);2866 const main_tokens = tree.nodes.items(.main_token);
28552867
2856 const operand_node = node_datas[node].lhs;2868 const operand_node = node_datas[node].lhs;
2857 const operand: zir.Inst.Ref = if (operand_node != 0) operand: {2869 const operand: zir.Inst.Ref = if (operand_node != 0) operand: {
2858 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(scope, operand_node)) .{2870 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
2859 .ptr = try gz.addNode(.ret_ptr, node),2871 .ptr = try gz.addNode(.ret_ptr, node),
2860 } else .{2872 } else .{
2861 .ty = try gz.addNode(.ret_type, node),2873 .ty = try gz.addNode(.ret_type, node),
...@@ -2876,7 +2888,7 @@ fn identifier(...@@ -2876,7 +2888,7 @@ fn identifier(
2876 defer tracy.end();2888 defer tracy.end();
28772889
2878 const mod = gz.astgen.mod;2890 const mod = gz.astgen.mod;
2879 const tree = scope.tree();2891 const tree = gz.tree();
2880 const main_tokens = tree.nodes.items(.main_token);2892 const main_tokens = tree.nodes.items(.main_token);
28812893
2882 const ident_token = main_tokens[ident];2894 const ident_token = main_tokens[ident];
...@@ -2961,7 +2973,7 @@ fn stringLiteral(...@@ -2961,7 +2973,7 @@ fn stringLiteral(
2961 rl: ResultLoc,2973 rl: ResultLoc,
2962 node: ast.Node.Index,2974 node: ast.Node.Index,
2963) InnerError!zir.Inst.Ref {2975) InnerError!zir.Inst.Ref {
2964 const tree = scope.tree();2976 const tree = gz.tree();
2965 const main_tokens = tree.nodes.items(.main_token);2977 const main_tokens = tree.nodes.items(.main_token);
2966 const string_bytes = &gz.astgen.string_bytes;2978 const string_bytes = &gz.astgen.string_bytes;
2967 const str_index = string_bytes.items.len;2979 const str_index = string_bytes.items.len;
...@@ -3048,7 +3060,7 @@ fn integerLiteral(...@@ -3048,7 +3060,7 @@ fn integerLiteral(
3048 rl: ResultLoc,3060 rl: ResultLoc,
3049 node: ast.Node.Index,3061 node: ast.Node.Index,
3050) InnerError!zir.Inst.Ref {3062) InnerError!zir.Inst.Ref {
3051 const tree = scope.tree();3063 const tree = gz.tree();
3052 const main_tokens = tree.nodes.items(.main_token);3064 const main_tokens = tree.nodes.items(.main_token);
3053 const int_token = main_tokens[node];3065 const int_token = main_tokens[node];
3054 const prefixed_bytes = tree.tokenSlice(int_token);3066 const prefixed_bytes = tree.tokenSlice(int_token);
...@@ -3070,8 +3082,8 @@ fn floatLiteral(...@@ -3070,8 +3082,8 @@ fn floatLiteral(
3070 rl: ResultLoc,3082 rl: ResultLoc,
3071 node: ast.Node.Index,3083 node: ast.Node.Index,
3072) InnerError!zir.Inst.Ref {3084) InnerError!zir.Inst.Ref {
3073 const arena = scope.arena();3085 const arena = gz.astgen.arena;
3074 const tree = scope.tree();3086 const tree = gz.tree();
3075 const main_tokens = tree.nodes.items(.main_token);3087 const main_tokens = tree.nodes.items(.main_token);
30763088
3077 const main_token = main_tokens[node];3089 const main_token = main_tokens[node];
...@@ -3088,10 +3100,7 @@ fn floatLiteral(...@@ -3088,10 +3100,7 @@ fn floatLiteral(
3088 .ty = Type.initTag(.comptime_float),3100 .ty = Type.initTag(.comptime_float),
3089 .val = try Value.Tag.float_128.create(arena, float_number),3101 .val = try Value.Tag.float_128.create(arena, float_number),
3090 };3102 };
3091 const result = try gz.add(.{3103 const result = try gz.addConst(typed_value);
3092 .tag = .@"const",
3093 .data = .{ .@"const" = typed_value },
3094 });
3095 return rvalue(gz, scope, rl, result, node);3104 return rvalue(gz, scope, rl, result, node);
3096}3105}
30973106
...@@ -3103,8 +3112,8 @@ fn asmExpr(...@@ -3103,8 +3112,8 @@ fn asmExpr(
3103 full: ast.full.Asm,3112 full: ast.full.Asm,
3104) InnerError!zir.Inst.Ref {3113) InnerError!zir.Inst.Ref {
3105 const mod = gz.astgen.mod;3114 const mod = gz.astgen.mod;
3106 const arena = scope.arena();3115 const arena = gz.astgen.arena;
3107 const tree = scope.tree();3116 const tree = gz.tree();
3108 const main_tokens = tree.nodes.items(.main_token);3117 const main_tokens = tree.nodes.items(.main_token);
3109 const node_datas = tree.nodes.items(.data);3118 const node_datas = tree.nodes.items(.data);
31103119
...@@ -3289,7 +3298,7 @@ fn typeOf(...@@ -3289,7 +3298,7 @@ fn typeOf(
3289 const result = try gz.addUnTok(.typeof, try expr(gz, scope, .none, params[0]), node);3298 const result = try gz.addUnTok(.typeof, try expr(gz, scope, .none, params[0]), node);
3290 return rvalue(gz, scope, rl, result, node);3299 return rvalue(gz, scope, rl, result, node);
3291 }3300 }
3292 const arena = scope.arena();3301 const arena = gz.astgen.arena;
3293 var items = try arena.alloc(zir.Inst.Ref, params.len);3302 var items = try arena.alloc(zir.Inst.Ref, params.len);
3294 for (params) |param, param_i| {3303 for (params) |param, param_i| {
3295 items[param_i] = try expr(gz, scope, .none, param);3304 items[param_i] = try expr(gz, scope, .none, param);
...@@ -3311,7 +3320,7 @@ fn builtinCall(...@@ -3311,7 +3320,7 @@ fn builtinCall(
3311 params: []const ast.Node.Index,3320 params: []const ast.Node.Index,
3312) InnerError!zir.Inst.Ref {3321) InnerError!zir.Inst.Ref {
3313 const mod = gz.astgen.mod;3322 const mod = gz.astgen.mod;
3314 const tree = scope.tree();3323 const tree = gz.tree();
3315 const main_tokens = tree.nodes.items(.main_token);3324 const main_tokens = tree.nodes.items(.main_token);
33163325
3317 const builtin_token = main_tokens[node];3326 const builtin_token = main_tokens[node];
...@@ -3608,8 +3617,7 @@ pub const simple_types = std.ComptimeStringMap(zir.Inst.Ref, .{...@@ -3608,8 +3617,7 @@ pub const simple_types = std.ComptimeStringMap(zir.Inst.Ref, .{
3608 .{ "false", .bool_false },3617 .{ "false", .bool_false },
3609});3618});
36103619
3611fn nodeMayNeedMemoryLocation(scope: *Scope, start_node: ast.Node.Index) bool {3620fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool {
3612 const tree = scope.tree();
3613 const node_tags = tree.nodes.items(.tag);3621 const node_tags = tree.nodes.items(.tag);
3614 const node_datas = tree.nodes.items(.data);3622 const node_datas = tree.nodes.items(.data);
3615 const main_tokens = tree.nodes.items(.main_token);3623 const main_tokens = tree.nodes.items(.main_token);
...@@ -3842,7 +3850,7 @@ fn rvalue(...@@ -3842,7 +3850,7 @@ fn rvalue(
3842 },3850 },
3843 .ref => {3851 .ref => {
3844 // We need a pointer but we have a value.3852 // We need a pointer but we have a value.
3845 const tree = scope.tree();3853 const tree = gz.tree();
3846 const src_token = tree.firstToken(src_node);3854 const src_token = tree.firstToken(src_node);
3847 return gz.addUnTok(.ref, result, src_token);3855 return gz.addUnTok(.ref, result, src_token);
3848 },3856 },
src/Module.zig+29-7
...@@ -78,9 +78,11 @@ next_anon_name_index: usize = 0,...@@ -78,9 +78,11 @@ next_anon_name_index: usize = 0,
78deletion_set: ArrayListUnmanaged(*Decl) = .{},78deletion_set: ArrayListUnmanaged(*Decl) = .{},
7979
80/// Error tags and their values, tag names are duped with mod.gpa.80/// Error tags and their values, tag names are duped with mod.gpa.
81global_error_set: std.StringHashMapUnmanaged(u16) = .{},81/// Corresponds with `error_name_list`.
82global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{},
8283
83/// error u16 -> []const u8 for fast lookups for @intToError at comptime84/// ErrorInt -> []const u8 for fast lookups for @intToError at comptime
85/// Corresponds with `global_error_set`.
84error_name_list: ArrayListUnmanaged([]const u8) = .{},86error_name_list: ArrayListUnmanaged([]const u8) = .{},
8587
86/// Keys are fully qualified paths88/// Keys are fully qualified paths
...@@ -108,6 +110,8 @@ emit_h: ?Compilation.EmitLoc,...@@ -108,6 +110,8 @@ emit_h: ?Compilation.EmitLoc,
108110
109compile_log_text: ArrayListUnmanaged(u8) = .{},111compile_log_text: ArrayListUnmanaged(u8) = .{},
110112
113pub const ErrorInt = u32;
114
111pub const Export = struct {115pub const Export = struct {
112 options: std.builtin.ExportOptions,116 options: std.builtin.ExportOptions,
113 src: LazySrcLoc,117 src: LazySrcLoc,
...@@ -341,6 +345,17 @@ pub const EmitH = struct {...@@ -341,6 +345,17 @@ pub const EmitH = struct {
341 fwd_decl: ArrayListUnmanaged(u8) = .{},345 fwd_decl: ArrayListUnmanaged(u8) = .{},
342};346};
343347
348/// Represents the data that an explicit error set syntax provides.
349pub const ErrorSet = struct {
350 owner_decl: *Decl,
351 /// Offset from Decl node index, points to the error set AST node.
352 node_offset: i32,
353 names_len: u32,
354 /// The string bytes are stored in the owner Decl arena.
355 /// They are in the same order they appear in the AST.
356 names_ptr: [*]const []const u8,
357};
358
344/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.359/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
345/// Extern functions do not have this data structure; they are represented by360/// Extern functions do not have this data structure; they are represented by
346/// the `Decl` only, with a `Value` tag of `extern_fn`.361/// the `Decl` only, with a `Value` tag of `extern_fn`.
...@@ -1363,6 +1378,13 @@ pub const Scope = struct {...@@ -1363,6 +1378,13 @@ pub const Scope = struct {
1363 return new_index;1378 return new_index;
1364 }1379 }
13651380
1381 pub fn addConst(gz: *GenZir, typed_value: *TypedValue) !zir.Inst.Ref {
1382 return gz.add(.{
1383 .tag = .@"const",
1384 .data = .{ .@"const" = typed_value },
1385 });
1386 }
1387
1366 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {1388 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
1367 return gz.astgen.indexToRef(try gz.addAsIndex(inst));1389 return gz.astgen.indexToRef(try gz.addAsIndex(inst));
1368 }1390 }
...@@ -3362,7 +3384,7 @@ fn createNewDecl(...@@ -3362,7 +3384,7 @@ fn createNewDecl(
3362}3384}
33633385
3364/// Get error value for error tag `name`.3386/// Get error value for error tag `name`.
3365pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(u16).Entry {3387pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry {
3366 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);3388 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
3367 if (gop.found_existing)3389 if (gop.found_existing)
3368 return gop.entry.*;3390 return gop.entry.*;
...@@ -3370,7 +3392,7 @@ pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged...@@ -3370,7 +3392,7 @@ pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged
3370 errdefer mod.global_error_set.removeAssertDiscard(name);3392 errdefer mod.global_error_set.removeAssertDiscard(name);
3371 try mod.error_name_list.ensureCapacity(mod.gpa, mod.error_name_list.items.len + 1);3393 try mod.error_name_list.ensureCapacity(mod.gpa, mod.error_name_list.items.len + 1);
3372 gop.entry.key = try mod.gpa.dupe(u8, name);3394 gop.entry.key = try mod.gpa.dupe(u8, name);
3373 gop.entry.value = @intCast(u16, mod.error_name_list.items.len);3395 gop.entry.value = @intCast(ErrorInt, mod.error_name_list.items.len);
3374 mod.error_name_list.appendAssumeCapacity(gop.entry.key);3396 mod.error_name_list.appendAssumeCapacity(gop.entry.key);
3375 return gop.entry.*;3397 return gop.entry.*;
3376}3398}
...@@ -3580,9 +3602,9 @@ pub fn createAnonymousDecl(...@@ -3580,9 +3602,9 @@ pub fn createAnonymousDecl(
3580 new_decl.analysis = .complete;3602 new_decl.analysis = .complete;
3581 new_decl.generation = mod.generation;3603 new_decl.generation = mod.generation;
35823604
3583 // TODO: This generates the Decl into the machine code file if it is of a type that is non-zero size.3605 // TODO: This generates the Decl into the machine code file if it is of a
3584 // We should be able to further improve the compiler to not omit Decls which are only referenced at3606 // type that is non-zero size. We should be able to further improve the
3585 // compile-time and not runtime.3607 // compiler to omit Decls which are only referenced at compile-time and not runtime.
3586 if (typed_value.ty.hasCodeGenBits()) {3608 if (typed_value.ty.hasCodeGenBits()) {
3587 try mod.comp.bin_file.allocateDeclIndexes(new_decl);3609 try mod.comp.bin_file.allocateDeclIndexes(new_decl);
3588 try mod.comp.work_queue.writeItem(.{ .codegen_decl = new_decl });3610 try mod.comp.work_queue.writeItem(.{ .codegen_decl = new_decl });
src/Sema.zig+77-92
...@@ -174,7 +174,6 @@ pub fn analyzeBody(...@@ -174,7 +174,6 @@ pub fn analyzeBody(
174 .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),174 .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),
175 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),175 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),
176 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false),176 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false),
177 .error_set => try sema.zirErrorSet(block, inst),
178 .error_union_type => try sema.zirErrorUnionType(block, inst),177 .error_union_type => try sema.zirErrorUnionType(block, inst),
179 .error_value => try sema.zirErrorValue(block, inst),178 .error_value => try sema.zirErrorValue(block, inst),
180 .error_to_int => try sema.zirErrorToInt(block, inst),179 .error_to_int => try sema.zirErrorToInt(block, inst),
...@@ -1409,41 +1408,6 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn...@@ -1409,41 +1408,6 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
1409 return sema.mod.constType(sema.arena, src, err_union_ty);1408 return sema.mod.constType(sema.arena, src, err_union_ty);
1410}1409}
14111410
1412fn zirErrorSet(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1413 const tracy = trace(@src());
1414 defer tracy.end();
1415
1416 if (true) @panic("TODO update for zir-memory-layout branch");
1417
1418 // The owner Decl arena will store the hashmap.
1419 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
1420 errdefer new_decl_arena.deinit();
1421
1422 const payload = try new_decl_arena.allocator.create(Value.Payload.ErrorSet);
1423 payload.* = .{
1424 .base = .{ .tag = .error_set },
1425 .data = .{
1426 .fields = .{},
1427 .decl = undefined, // populated below
1428 },
1429 };
1430 try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, inst.positionals.fields.len));
1431
1432 for (inst.positionals.fields) |field_name| {
1433 const entry = try sema.mod.getErrorValue(field_name);
1434 if (payload.data.fields.fetchPutAssumeCapacity(entry.key, {})) |_| {
1435 return sema.mod.fail(&block.base, inst.base.src, "duplicate error: '{s}'", .{field_name});
1436 }
1437 }
1438 // TODO create name in format "error:line:column"
1439 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
1440 .ty = Type.initTag(.type),
1441 .val = Value.initPayload(&payload.base),
1442 });
1443 payload.data.decl = new_decl;
1444 return sema.analyzeDeclVal(block, inst.base.src, new_decl);
1445}
1446
1447fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1411fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1448 const tracy = trace(@src());1412 const tracy = trace(@src());
1449 defer tracy.end();1413 defer tracy.end();
...@@ -1537,71 +1501,67 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn...@@ -1537,71 +1501,67 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
1537 if (lhs_ty.zigTypeTag() != .ErrorSet)1501 if (lhs_ty.zigTypeTag() != .ErrorSet)
1538 return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{lhs_ty});1502 return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{lhs_ty});
15391503
1540 // anything merged with anyerror is anyerror1504 // Anything merged with anyerror is anyerror.
1541 if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror)1505 if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) {
1542 return sema.mod.constInst(sema.arena, src, .{1506 return sema.mod.constInst(sema.arena, src, .{
1543 .ty = Type.initTag(.type),1507 .ty = Type.initTag(.type),
1544 .val = Value.initTag(.anyerror_type),1508 .val = Value.initTag(.anyerror_type),
1545 });1509 });
1546 // The declarations arena will store the hashmap.1510 }
1547 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);1511 // When we support inferred error sets, we'll want to use a data structure that can
1548 errdefer new_decl_arena.deinit();1512 // represent a merged set of errors without forcing them to be resolved here. Until then
15491513 // we re-use the same data structure that is used for explicit error set declarations.
1550 const payload = try new_decl_arena.allocator.create(Value.Payload.ErrorSet);1514 var set: std.StringHashMapUnmanaged(void) = .{};
1551 payload.* = .{1515 defer set.deinit(sema.gpa);
1552 .base = .{ .tag = .error_set },
1553 .data = .{
1554 .fields = .{},
1555 .decl = undefined, // populated below
1556 },
1557 };
1558 try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, switch (rhs_ty.tag()) {
1559 .error_set_single => 1,
1560 .error_set => rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size,
1561 else => unreachable,
1562 } + switch (lhs_ty.tag()) {
1563 .error_set_single => 1,
1564 .error_set => lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size,
1565 else => unreachable,
1566 }));
15671516
1568 switch (lhs_ty.tag()) {1517 switch (lhs_ty.tag()) {
1569 .error_set_single => {1518 .error_set_single => {
1570 const name = lhs_ty.castTag(.error_set_single).?.data;1519 const name = lhs_ty.castTag(.error_set_single).?.data;
1571 payload.data.fields.putAssumeCapacity(name, {});1520 try set.put(sema.gpa, name, {});
1572 },1521 },
1573 .error_set => {1522 .error_set => {
1574 var multiple = lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;1523 const lhs_set = lhs_ty.castTag(.error_set).?.data;
1575 var it = multiple.iterator();1524 try set.ensureCapacity(sema.gpa, set.count() + lhs_set.names_len);
1576 while (it.next()) |entry| {1525 for (lhs_set.names_ptr[0..lhs_set.names_len]) |name| {
1577 payload.data.fields.putAssumeCapacity(entry.key, entry.value);1526 set.putAssumeCapacityNoClobber(name, {});
1578 }1527 }
1579 },1528 },
1580 else => unreachable,1529 else => unreachable,
1581 }1530 }
1582
1583 switch (rhs_ty.tag()) {1531 switch (rhs_ty.tag()) {
1584 .error_set_single => {1532 .error_set_single => {
1585 const name = rhs_ty.castTag(.error_set_single).?.data;1533 const name = rhs_ty.castTag(.error_set_single).?.data;
1586 payload.data.fields.putAssumeCapacity(name, {});1534 try set.put(sema.gpa, name, {});
1587 },1535 },
1588 .error_set => {1536 .error_set => {
1589 var multiple = rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;1537 const rhs_set = rhs_ty.castTag(.error_set).?.data;
1590 var it = multiple.iterator();1538 try set.ensureCapacity(sema.gpa, set.count() + rhs_set.names_len);
1591 while (it.next()) |entry| {1539 for (rhs_set.names_ptr[0..rhs_set.names_len]) |name| {
1592 payload.data.fields.putAssumeCapacity(entry.key, entry.value);1540 set.putAssumeCapacity(name, {});
1593 }1541 }
1594 },1542 },
1595 else => unreachable,1543 else => unreachable,
1596 }1544 }
1597 // TODO create name in format "error:line:column"1545
1598 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{1546 const new_names = try sema.arena.alloc([]const u8, set.count());
1547 var it = set.iterator();
1548 var i: usize = 0;
1549 while (it.next()) |entry| : (i += 1) {
1550 new_names[i] = entry.key;
1551 }
1552
1553 const new_error_set = try sema.arena.create(Module.ErrorSet);
1554 new_error_set.* = .{
1555 .owner_decl = sema.owner_decl,
1556 .node_offset = inst_data.src_node,
1557 .names_ptr = new_names.ptr,
1558 .names_len = @intCast(u32, new_names.len),
1559 };
1560 const error_set_ty = try Type.Tag.error_set.create(sema.arena, new_error_set);
1561 return sema.mod.constInst(sema.arena, src, .{
1599 .ty = Type.initTag(.type),1562 .ty = Type.initTag(.type),
1600 .val = Value.initPayload(&payload.base),1563 .val = try Value.Tag.ty.create(sema.arena, error_set_ty),
1601 });1564 });
1602 payload.data.decl = new_decl;
1603
1604 return sema.analyzeDeclVal(block, src, new_decl);
1605}1565}
16061566
1607fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1567fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
...@@ -3441,20 +3401,25 @@ fn namedFieldPtr(...@@ -3441,20 +3401,25 @@ fn namedFieldPtr(
3441 const child_type = try val.toType(sema.arena);3401 const child_type = try val.toType(sema.arena);
3442 switch (child_type.zigTypeTag()) {3402 switch (child_type.zigTypeTag()) {
3443 .ErrorSet => {3403 .ErrorSet => {
3444 var name: []const u8 = undefined;
3445 // TODO resolve inferred error sets3404 // TODO resolve inferred error sets
3446 if (val.castTag(.error_set)) |payload|3405 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {
3447 name = (payload.data.fields.getEntry(field_name) orelse return sema.mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{ field_name, child_type })).key3406 const error_set = payload.data;
3448 else3407 // TODO this is O(N). I'm putting off solving this until we solve inferred
3449 name = (try sema.mod.getErrorValue(field_name)).key;3408 // error sets at the same time.
34503409 const names = error_set.names_ptr[0..error_set.names_len];
3451 const result_type = if (child_type.tag() == .anyerror)3410 for (names) |name| {
3452 try Type.Tag.error_set_single.create(sema.arena, name)3411 if (mem.eql(u8, field_name, name)) {
3453 else3412 break :blk name;
3454 child_type;3413 }
3414 }
3415 return sema.mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{
3416 field_name,
3417 child_type,
3418 });
3419 } else (try sema.mod.getErrorValue(field_name)).key;
34553420
3456 return sema.mod.constInst(sema.arena, src, .{3421 return sema.mod.constInst(sema.arena, src, .{
3457 .ty = try sema.mod.simplePtrType(sema.arena, result_type, false, .One),3422 .ty = try sema.mod.simplePtrType(sema.arena, child_type, false, .One),
3458 .val = try Value.Tag.ref_val.create(3423 .val = try Value.Tag.ref_val.create(
3459 sema.arena,3424 sema.arena,
3460 try Value.Tag.@"error".create(sema.arena, .{3425 try Value.Tag.@"error".create(sema.arena, .{
...@@ -4201,15 +4166,35 @@ fn wrapErrorUnion(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: *Inst...@@ -4201,15 +4166,35 @@ fn wrapErrorUnion(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: *Inst
4201 } else switch (err_union.data.error_set.tag()) {4166 } else switch (err_union.data.error_set.tag()) {
4202 .anyerror => val,4167 .anyerror => val,
4203 .error_set_single => blk: {4168 .error_set_single => blk: {
4169 const expected_name = val.castTag(.@"error").?.data.name;
4204 const n = err_union.data.error_set.castTag(.error_set_single).?.data;4170 const n = err_union.data.error_set.castTag(.error_set_single).?.data;
4205 if (!mem.eql(u8, val.castTag(.@"error").?.data.name, n))4171 if (!mem.eql(u8, expected_name, n)) {
4206 return sema.mod.fail(&block.base, inst.src, "expected type '{}', found type '{}'", .{ err_union.data.error_set, inst.ty });4172 return sema.mod.fail(
4173 &block.base,
4174 inst.src,
4175 "expected type '{}', found type '{}'",
4176 .{ err_union.data.error_set, inst.ty },
4177 );
4178 }
4207 break :blk val;4179 break :blk val;
4208 },4180 },
4209 .error_set => blk: {4181 .error_set => blk: {
4210 const f = err_union.data.error_set.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields;4182 const expected_name = val.castTag(.@"error").?.data.name;
4211 if (f.get(val.castTag(.@"error").?.data.name) == null)4183 const error_set = err_union.data.error_set.castTag(.error_set).?.data;
4212 return sema.mod.fail(&block.base, inst.src, "expected type '{}', found type '{}'", .{ err_union.data.error_set, inst.ty });4184 const names = error_set.names_ptr[0..error_set.names_len];
4185 // TODO this is O(N). I'm putting off solving this until we solve inferred
4186 // error sets at the same time.
4187 const found = for (names) |name| {
4188 if (mem.eql(u8, expected_name, name)) break true;
4189 } else false;
4190 if (!found) {
4191 return sema.mod.fail(
4192 &block.base,
4193 inst.src,
4194 "expected type '{}', found type '{}'",
4195 .{ err_union.data.error_set, inst.ty },
4196 );
4197 }
4213 break :blk val;4198 break :blk val;
4214 },4199 },
4215 else => unreachable,4200 else => unreachable,
src/type.zig+11-4
...@@ -606,7 +606,7 @@ pub const Type = extern union {...@@ -606,7 +606,7 @@ pub const Type = extern union {
606 .payload = try payload.payload.copy(allocator),606 .payload = try payload.payload.copy(allocator),
607 });607 });
608 },608 },
609 .error_set => return self.copyPayloadShallow(allocator, Payload.Decl),609 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
610 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),610 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
611 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),611 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
612612
...@@ -831,8 +831,8 @@ pub const Type = extern union {...@@ -831,8 +831,8 @@ pub const Type = extern union {
831 continue;831 continue;
832 },832 },
833 .error_set => {833 .error_set => {
834 const decl = ty.castTag(.error_set).?.data;834 const error_set = ty.castTag(.error_set).?.data;
835 return out_stream.writeAll(std.mem.spanZ(decl.name));835 return out_stream.writeAll(std.mem.spanZ(error_set.owner_decl.name));
836 },836 },
837 .error_set_single => {837 .error_set_single => {
838 const name = ty.castTag(.error_set_single).?.data;838 const name = ty.castTag(.error_set_single).?.data;
...@@ -3464,7 +3464,7 @@ pub const Type = extern union {...@@ -3464,7 +3464,7 @@ pub const Type = extern union {
3464 .int_unsigned,3464 .int_unsigned,
3465 => Payload.Bits,3465 => Payload.Bits,
34663466
3467 .error_set => Payload.Decl,3467 .error_set => Payload.ErrorSet,
34683468
3469 .array => Payload.Array,3469 .array => Payload.Array,
3470 .array_sentinel => Payload.ArraySentinel,3470 .array_sentinel => Payload.ArraySentinel,
...@@ -3548,6 +3548,13 @@ pub const Type = extern union {...@@ -3548,6 +3548,13 @@ pub const Type = extern union {
3548 },3548 },
3549 };3549 };
35503550
3551 pub const ErrorSet = struct {
3552 pub const base_tag = Tag.error_set;
3553
3554 base: Payload = Payload{ .tag = base_tag },
3555 data: *Module.ErrorSet,
3556 };
3557
3551 pub const Pointer = struct {3558 pub const Pointer = struct {
3552 pub const base_tag = Tag.pointer;3559 pub const base_tag = Tag.pointer;
35533560
src/value.zig+1-46
...@@ -102,7 +102,6 @@ pub const Value = extern union {...@@ -102,7 +102,6 @@ pub const Value = extern union {
102 float_64,102 float_64,
103 float_128,103 float_128,
104 enum_literal,104 enum_literal,
105 error_set,
106 @"error",105 @"error",
107 error_union,106 error_union,
108 /// This is a special value that tracks a set of types that have been stored107 /// This is a special value that tracks a set of types that have been stored
...@@ -196,7 +195,6 @@ pub const Value = extern union {...@@ -196,7 +195,6 @@ pub const Value = extern union {
196 .float_32 => Payload.Float_32,195 .float_32 => Payload.Float_32,
197 .float_64 => Payload.Float_64,196 .float_64 => Payload.Float_64,
198 .float_128 => Payload.Float_128,197 .float_128 => Payload.Float_128,
199 .error_set => Payload.ErrorSet,
200 .@"error" => Payload.Error,198 .@"error" => Payload.Error,
201 .inferred_alloc => Payload.InferredAlloc,199 .inferred_alloc => Payload.InferredAlloc,
202 };200 };
...@@ -404,7 +402,6 @@ pub const Value = extern union {...@@ -404,7 +402,6 @@ pub const Value = extern union {
404 return Value{ .ptr_otherwise = &new_payload.base };402 return Value{ .ptr_otherwise = &new_payload.base };
405 },403 },
406404
407 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
408 .inferred_alloc => unreachable,405 .inferred_alloc => unreachable,
409 }406 }
410 }407 }
...@@ -515,15 +512,6 @@ pub const Value = extern union {...@@ -515,15 +512,6 @@ pub const Value = extern union {
515 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),512 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
516 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),513 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
517 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),514 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
518 .error_set => {
519 const error_set = val.castTag(.error_set).?.data;
520 try out_stream.writeAll("error{");
521 var it = error_set.fields.iterator();
522 while (it.next()) |entry| {
523 try out_stream.print("{},", .{entry.value});
524 }
525 return out_stream.writeAll("}");
526 },
527 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),515 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
528 // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that516 // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
529 .error_union => return out_stream.print("error_union_val({})", .{val.castTag(.error_union).?.data}),517 .error_union => return out_stream.print("error_union_val({})", .{val.castTag(.error_union).?.data}),
...@@ -608,10 +596,6 @@ pub const Value = extern union {...@@ -608,10 +596,6 @@ pub const Value = extern union {
608 };596 };
609 return Type.initPayload(&new.base);597 return Type.initPayload(&new.base);
610 },598 },
611 .error_set => {
612 const payload = self.castTag(.error_set).?.data;
613 return Type.Tag.error_set.create(allocator, payload.decl);
614 },
615599
616 .undef,600 .undef,
617 .zero,601 .zero,
...@@ -711,7 +695,6 @@ pub const Value = extern union {...@@ -711,7 +695,6 @@ pub const Value = extern union {
711 .unreachable_value,695 .unreachable_value,
712 .empty_array,696 .empty_array,
713 .enum_literal,697 .enum_literal,
714 .error_set,
715 .error_union,698 .error_union,
716 .@"error",699 .@"error",
717 .empty_struct_value,700 .empty_struct_value,
...@@ -799,7 +782,6 @@ pub const Value = extern union {...@@ -799,7 +782,6 @@ pub const Value = extern union {
799 .unreachable_value,782 .unreachable_value,
800 .empty_array,783 .empty_array,
801 .enum_literal,784 .enum_literal,
802 .error_set,
803 .@"error",785 .@"error",
804 .error_union,786 .error_union,
805 .empty_struct_value,787 .empty_struct_value,
...@@ -887,7 +869,6 @@ pub const Value = extern union {...@@ -887,7 +869,6 @@ pub const Value = extern union {
887 .unreachable_value,869 .unreachable_value,
888 .empty_array,870 .empty_array,
889 .enum_literal,871 .enum_literal,
890 .error_set,
891 .@"error",872 .@"error",
892 .error_union,873 .error_union,
893 .empty_struct_value,874 .empty_struct_value,
...@@ -1003,7 +984,6 @@ pub const Value = extern union {...@@ -1003,7 +984,6 @@ pub const Value = extern union {
1003 .unreachable_value,984 .unreachable_value,
1004 .empty_array,985 .empty_array,
1005 .enum_literal,986 .enum_literal,
1006 .error_set,
1007 .@"error",987 .@"error",
1008 .error_union,988 .error_union,
1009 .empty_struct_value,989 .empty_struct_value,
...@@ -1095,7 +1075,6 @@ pub const Value = extern union {...@@ -1095,7 +1075,6 @@ pub const Value = extern union {
1095 .unreachable_value,1075 .unreachable_value,
1096 .empty_array,1076 .empty_array,
1097 .enum_literal,1077 .enum_literal,
1098 .error_set,
1099 .@"error",1078 .@"error",
1100 .error_union,1079 .error_union,
1101 .empty_struct_value,1080 .empty_struct_value,
...@@ -1256,7 +1235,6 @@ pub const Value = extern union {...@@ -1256,7 +1235,6 @@ pub const Value = extern union {
1256 .void_value,1235 .void_value,
1257 .unreachable_value,1236 .unreachable_value,
1258 .enum_literal,1237 .enum_literal,
1259 .error_set,
1260 .@"error",1238 .@"error",
1261 .error_union,1239 .error_union,
1262 .empty_struct_value,1240 .empty_struct_value,
...@@ -1335,7 +1313,6 @@ pub const Value = extern union {...@@ -1335,7 +1313,6 @@ pub const Value = extern union {
1335 .unreachable_value,1313 .unreachable_value,
1336 .empty_array,1314 .empty_array,
1337 .enum_literal,1315 .enum_literal,
1338 .error_set,
1339 .@"error",1316 .@"error",
1340 .error_union,1317 .error_union,
1341 .empty_struct_value,1318 .empty_struct_value,
...@@ -1476,15 +1453,10 @@ pub const Value = extern union {...@@ -1476,15 +1453,10 @@ pub const Value = extern union {
1476 .enum_literal_type,1453 .enum_literal_type,
1477 .ty,1454 .ty,
1478 => {1455 => {
1479 // Directly return Type.hash, toType can only fail for .int_type and .error_set.1456 // Directly return Type.hash, toType can only fail for .int_type.
1480 var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{});1457 var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{});
1481 return (self.toType(&allocator.allocator) catch unreachable).hash();1458 return (self.toType(&allocator.allocator) catch unreachable).hash();
1482 },1459 },
1483 .error_set => {
1484 // Payload.decl should be same for all instances of the type.
1485 const payload = self.castTag(.error_set).?.data;
1486 std.hash.autoHash(&hasher, payload.decl);
1487 },
1488 .int_type => {1460 .int_type => {
1489 const payload = self.castTag(.int_type).?.data;1461 const payload = self.castTag(.int_type).?.data;
1490 var int_payload = Type.Payload.Bits{1462 var int_payload = Type.Payload.Bits{
...@@ -1656,7 +1628,6 @@ pub const Value = extern union {...@@ -1656,7 +1628,6 @@ pub const Value = extern union {
1656 .unreachable_value,1628 .unreachable_value,
1657 .empty_array,1629 .empty_array,
1658 .enum_literal,1630 .enum_literal,
1659 .error_set,
1660 .@"error",1631 .@"error",
1661 .error_union,1632 .error_union,
1662 .empty_struct_value,1633 .empty_struct_value,
...@@ -1744,7 +1715,6 @@ pub const Value = extern union {...@@ -1744,7 +1715,6 @@ pub const Value = extern union {
1744 .void_value,1715 .void_value,
1745 .unreachable_value,1716 .unreachable_value,
1746 .enum_literal,1717 .enum_literal,
1747 .error_set,
1748 .@"error",1718 .@"error",
1749 .error_union,1719 .error_union,
1750 .empty_struct_value,1720 .empty_struct_value,
...@@ -1849,7 +1819,6 @@ pub const Value = extern union {...@@ -1849,7 +1819,6 @@ pub const Value = extern union {
1849 .float_128,1819 .float_128,
1850 .void_value,1820 .void_value,
1851 .enum_literal,1821 .enum_literal,
1852 .error_set,
1853 .@"error",1822 .@"error",
1854 .error_union,1823 .error_union,
1855 .empty_struct_value,1824 .empty_struct_value,
...@@ -1933,7 +1902,6 @@ pub const Value = extern union {...@@ -1933,7 +1902,6 @@ pub const Value = extern union {
1933 .float_128,1902 .float_128,
1934 .void_value,1903 .void_value,
1935 .enum_literal,1904 .enum_literal,
1936 .error_set,
1937 .empty_struct_value,1905 .empty_struct_value,
1938 => null,1906 => null,
19391907
...@@ -2012,7 +1980,6 @@ pub const Value = extern union {...@@ -2012,7 +1980,6 @@ pub const Value = extern union {
2012 .single_const_pointer_to_comptime_int_type,1980 .single_const_pointer_to_comptime_int_type,
2013 .const_slice_u8_type,1981 .const_slice_u8_type,
2014 .enum_literal_type,1982 .enum_literal_type,
2015 .error_set,
2016 => true,1983 => true,
20171984
2018 .zero,1985 .zero,
...@@ -2156,18 +2123,6 @@ pub const Value = extern union {...@@ -2156,18 +2123,6 @@ pub const Value = extern union {
2156 data: f128,2123 data: f128,
2157 };2124 };
21582125
2159 /// TODO move to type.zig
2160 pub const ErrorSet = struct {
2161 pub const base_tag = Tag.error_set;
2162
2163 base: Payload = .{ .tag = base_tag },
2164 data: struct {
2165 /// TODO revisit this when we have the concept of the error tag type
2166 fields: std.StringHashMapUnmanaged(void),
2167 decl: *Module.Decl,
2168 },
2169 };
2170
2171 pub const Error = struct {2126 pub const Error = struct {
2172 base: Payload = .{ .tag = .@"error" },2127 base: Payload = .{ .tag = .@"error" },
2173 data: struct {2128 data: struct {
src/zir.zig+13-9
...@@ -314,11 +314,6 @@ pub const Inst = struct {...@@ -314,11 +314,6 @@ pub const Inst = struct {
314 /// Create a `E!T` type.314 /// Create a `E!T` type.
315 /// Uses the `pl_node` field with `Bin` payload.315 /// Uses the `pl_node` field with `Bin` payload.
316 error_union_type,316 error_union_type,
317 /// Create an error set. TODO can't we just do this in astgen? reconsider
318 /// memory layout of error sets. if astgen wants to make Sema do the work,
319 /// this ZIR instruction could just be an AST node index. If astgen wants to
320 /// do the work, it could use a const instruction.
321 error_set,
322 /// `error.Foo` syntax. Uses the `str_tok` field of the Data union.317 /// `error.Foo` syntax. Uses the `str_tok` field of the Data union.
323 error_value,318 error_value,
324 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer319 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
...@@ -742,7 +737,6 @@ pub const Inst = struct {...@@ -742,7 +737,6 @@ pub const Inst = struct {
742 .merge_error_sets,737 .merge_error_sets,
743 .error_union_type,738 .error_union_type,
744 .bit_not,739 .bit_not,
745 .error_set,
746 .error_value,740 .error_value,
747 .slice_start,741 .slice_start,
748 .slice_end,742 .slice_end,
...@@ -1459,8 +1453,6 @@ const Writer = struct {...@@ -1459,8 +1453,6 @@ const Writer = struct {
1459 .asm_volatile,1453 .asm_volatile,
1460 .elem_ptr_node,1454 .elem_ptr_node,
1461 .elem_val_node,1455 .elem_val_node,
1462 .field_ptr,
1463 .field_val,
1464 .field_ptr_named,1456 .field_ptr_named,
1465 .field_val_named,1457 .field_val_named,
1466 .floatcast,1458 .floatcast,
...@@ -1519,6 +1511,10 @@ const Writer = struct {...@@ -1519,6 +1511,10 @@ const Writer = struct {
1519 .decl_val,1511 .decl_val,
1520 => try self.writePlNodeDecl(stream, inst),1512 => try self.writePlNodeDecl(stream, inst),
15211513
1514 .field_ptr,
1515 .field_val,
1516 => try self.writePlNodeField(stream, inst),
1517
1522 .as_node => try self.writeAs(stream, inst),1518 .as_node => try self.writeAs(stream, inst),
15231519
1524 .breakpoint,1520 .breakpoint,
...@@ -1544,7 +1540,6 @@ const Writer = struct {...@@ -1544,7 +1540,6 @@ const Writer = struct {
1544 .bitcast,1540 .bitcast,
1545 .bitcast_ref,1541 .bitcast_ref,
1546 .bitcast_result_ptr,1542 .bitcast_result_ptr,
1547 .error_set,
1548 .store_to_inferred_ptr,1543 .store_to_inferred_ptr,
1549 => try stream.writeAll("TODO)"),1544 => try stream.writeAll("TODO)"),
1550 }1545 }
...@@ -1733,6 +1728,15 @@ const Writer = struct {...@@ -1733,6 +1728,15 @@ const Writer = struct {
1733 try self.writeSrc(stream, inst_data.src());1728 try self.writeSrc(stream, inst_data.src());
1734 }1729 }
17351730
1731 fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1732 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1733 const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data;
1734 const name = self.code.nullTerminatedString(extra.field_name_start);
1735 try self.writeInstRef(stream, extra.lhs);
1736 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});
1737 try self.writeSrc(stream, inst_data.src());
1738 }
1739
1736 fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {1740 fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1737 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1741 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1738 const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;1742 const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;
test/stage2/test.zig+32-32
...@@ -1565,37 +1565,37 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1565,37 +1565,37 @@ pub fn addCases(ctx: *TestContext) !void {
1565 \\}1565 \\}
1566 , "");1566 , "");
1567 }1567 }
1568 //{1568 {
1569 // var case = ctx.exe("merge error sets", linux_x64);1569 var case = ctx.exe("merge error sets", linux_x64);
15701570
1571 // case.addCompareOutput(1571 case.addCompareOutput(
1572 // \\export fn _start() noreturn {1572 \\export fn _start() noreturn {
1573 // \\ const E = error{ A, B, D } || error { A, B, C };1573 \\ const E = error{ A, B, D } || error { A, B, C };
1574 // \\ const a = E.A;1574 \\ const a = E.A;
1575 // \\ const b = E.B;1575 \\ const b = E.B;
1576 // \\ const c = E.C;1576 \\ const c = E.C;
1577 // \\ const d = E.D;1577 \\ const d = E.D;
1578 // \\ const E2 = error { X, Y } || @TypeOf(error.Z);1578 \\ const E2 = error { X, Y } || @TypeOf(error.Z);
1579 // \\ const x = E2.X;1579 \\ const x = E2.X;
1580 // \\ const y = E2.Y;1580 \\ const y = E2.Y;
1581 // \\ const z = E2.Z;1581 \\ const z = E2.Z;
1582 // \\ assert(anyerror || error { Z } == anyerror);1582 \\ assert(anyerror || error { Z } == anyerror);
1583 // \\ exit();1583 \\ exit();
1584 // \\}1584 \\}
1585 // \\fn assert(b: bool) void {1585 \\fn assert(b: bool) void {
1586 // \\ if (!b) unreachable;1586 \\ if (!b) unreachable;
1587 // \\}1587 \\}
1588 // \\fn exit() noreturn {1588 \\fn exit() noreturn {
1589 // \\ asm volatile ("syscall"1589 \\ asm volatile ("syscall"
1590 // \\ :1590 \\ :
1591 // \\ : [number] "{rax}" (231),1591 \\ : [number] "{rax}" (231),
1592 // \\ [arg1] "{rdi}" (0)1592 \\ [arg1] "{rdi}" (0)
1593 // \\ : "rcx", "r11", "memory"1593 \\ : "rcx", "r11", "memory"
1594 // \\ );1594 \\ );
1595 // \\ unreachable;1595 \\ unreachable;
1596 // \\}1596 \\}
1597 // ,1597 ,
1598 // "",1598 "",
1599 // );1599 );
1600 //}1600 }
1601}1601}