authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-12-16 01:45:41+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-12-21 01:41:50+01:00
logcd733ceb852369427301fbb526b82ad4407d0607
tree9673ab520b07e73650be9038b7db62c628795e42
parentea913846c2d45a6e4862d5eaf94773ea880bfeab

stage2: replace ErrorSet and ErrorSetMerged arrays with hash maps


3 files changed, 55 insertions(+), 87 deletions(-)

src/Module.zig+2-6
......@@ -796,15 +796,11 @@ pub const ErrorSet = struct {
796796 owner_decl: *Decl,
797797 /// Offset from Decl node index, points to the error set AST node.
798798 node_offset: i32,
799 names_len: u32,
800799 /// The string bytes are stored in the owner Decl arena.
801800 /// They are in the same order they appear in the AST.
802 /// The length is given by `names_len`.
803 names_ptr: [*]const []const u8,
801 names: NameMap,
804802
805 pub fn names(self: ErrorSet) []const []const u8 {
806 return self.names_ptr[0..self.names_len];
807 }
803 pub const NameMap = std.StringArrayHashMapUnmanaged(void);
808804
809805 pub fn srcLoc(self: ErrorSet) SrcLoc {
810806 return .{
src/Sema.zig+44-73
......@@ -2025,15 +2025,22 @@ fn zirErrorSetDecl(
20252025 }, type_name);
20262026 new_decl.owns_tv = true;
20272027 errdefer sema.mod.abortAnonDecl(new_decl);
2028 const names = try new_decl_arena_allocator.alloc([]const u8, fields.len);
2029 for (fields) |str_index, i| {
2030 names[i] = try new_decl_arena_allocator.dupe(u8, sema.code.nullTerminatedString(str_index));
2028
2029 var names = Module.ErrorSet.NameMap{};
2030 try names.ensureUnusedCapacity(new_decl_arena_allocator, fields.len);
2031 for (fields) |str_index| {
2032 const name = try new_decl_arena_allocator.dupe(u8, sema.code.nullTerminatedString(str_index));
2033
2034 // TODO: This check should be performed in AstGen instead.
2035 const result = names.getOrPutAssumeCapacity(name);
2036 if (result.found_existing) {
2037 return sema.fail(block, src, "duplicate error set field {s}", .{name});
2038 }
20312039 }
20322040 error_set.* = .{
20332041 .owner_decl = new_decl,
20342042 .node_offset = inst_data.src_node,
2035 .names_ptr = names.ptr,
2036 .names_len = @intCast(u32, names.len),
2043 .names = names,
20372044 };
20382045 try new_decl.finalizeNewArena(&new_decl_arena);
20392046 return sema.analyzeDeclVal(block, src, new_decl);
......@@ -4556,63 +4563,43 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
45564563 return Air.Inst.Ref.anyerror_type;
45574564 }
45584565 // Resolve both error sets now.
4559 var set: std.StringHashMapUnmanaged(void) = .{};
4560 defer set.deinit(sema.gpa);
4561
4562 switch (lhs_ty.tag()) {
4563 .error_set_single => {
4564 const name = lhs_ty.castTag(.error_set_single).?.data;
4565 try set.put(sema.gpa, name, {});
4566 },
4567 .error_set_merged => {
4568 const names = lhs_ty.castTag(.error_set_merged).?.data;
4569 for (names) |name| {
4570 try set.put(sema.gpa, name, {});
4571 }
4572 },
4573 .error_set => {
4574 const lhs_set = lhs_ty.castTag(.error_set).?.data;
4575 try set.ensureUnusedCapacity(sema.gpa, lhs_set.names_len);
4576 for (lhs_set.names_ptr[0..lhs_set.names_len]) |name| {
4577 set.putAssumeCapacityNoClobber(name, {});
4578 }
4566 const lhs_names = switch (lhs_ty.tag()) {
4567 .error_set_single => blk: {
4568 // Work around coercion problems
4569 const tmp: *const [1][]const u8 = &lhs_ty.castTag(.error_set_single).?.data;
4570 break :blk tmp;
45794571 },
4572 .error_set_merged => lhs_ty.castTag(.error_set_merged).?.data.keys(),
4573 .error_set => lhs_ty.castTag(.error_set).?.data.names.keys(),
45804574 else => unreachable,
4581 }
4582 switch (rhs_ty.tag()) {
4583 .error_set_single => {
4584 const name = rhs_ty.castTag(.error_set_single).?.data;
4585 try set.put(sema.gpa, name, {});
4586 },
4587 .error_set_merged => {
4588 const names = rhs_ty.castTag(.error_set_merged).?.data;
4589 for (names) |name| {
4590 try set.put(sema.gpa, name, {});
4591 }
4592 },
4593 .error_set => {
4594 const rhs_set = rhs_ty.castTag(.error_set).?.data;
4595 try set.ensureUnusedCapacity(sema.gpa, rhs_set.names_len);
4596 for (rhs_set.names_ptr[0..rhs_set.names_len]) |name| {
4597 set.putAssumeCapacity(name, {});
4598 }
4575 };
4576
4577 const rhs_names = switch (rhs_ty.tag()) {
4578 .error_set_single => blk: {
4579 const tmp: *const [1][]const u8 = &rhs_ty.castTag(.error_set_single).?.data;
4580 break :blk tmp;
45994581 },
4582 .error_set_merged => rhs_ty.castTag(.error_set_merged).?.data.keys(),
4583 .error_set => rhs_ty.castTag(.error_set).?.data.names.keys(),
46004584 else => unreachable,
4601 }
4585 };
46024586
46034587 // TODO do we really want to create a Decl for this?
46044588 // The reason we do it right now is for memory management.
46054589 var anon_decl = try block.startAnonDecl();
46064590 defer anon_decl.deinit();
46074591
4608 const new_names = try anon_decl.arena().alloc([]const u8, set.count());
4609 var it = set.keyIterator();
4610 var i: usize = 0;
4611 while (it.next()) |key| : (i += 1) {
4612 new_names[i] = key.*;
4592 var names = Module.ErrorSet.NameMap{};
4593 // TODO: Guess is an upper bound, but maybe this needs to be reduced by computing the exact size first.
4594 try names.ensureUnusedCapacity(anon_decl.arena(), @intCast(u32, lhs_names.len + rhs_names.len));
4595 for (lhs_names) |name| {
4596 names.putAssumeCapacityNoClobber(name, {});
4597 }
4598 for (rhs_names) |name| {
4599 names.putAssumeCapacity(name, {});
46134600 }
46144601
4615 const err_set_ty = try Type.Tag.error_set_merged.create(anon_decl.arena(), new_names);
4602 const err_set_ty = try Type.Tag.error_set_merged.create(anon_decl.arena(), names);
46164603 const err_set_decl = try anon_decl.finish(
46174604 Type.type,
46184605 try Value.Tag.ty.create(anon_decl.arena(), err_set_ty),
......@@ -11425,14 +11412,8 @@ fn fieldVal(
1142511412 switch (child_type.zigTypeTag()) {
1142611413 .ErrorSet => {
1142711414 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {
11428 const error_set = payload.data;
11429 // TODO this is O(N). I'm putting off solving this until we solve inferred
11430 // error sets at the same time.
11431 const names = error_set.names_ptr[0..error_set.names_len];
11432 for (names) |name| {
11433 if (mem.eql(u8, field_name, name)) {
11434 break :blk name;
11435 }
11415 if (payload.data.names.getEntry(field_name)) |entry| {
11416 break :blk entry.key_ptr.*;
1143611417 }
1143711418 return sema.fail(block, src, "no error named '{s}' in '{}'", .{
1143811419 field_name, child_type,
......@@ -11630,14 +11611,8 @@ fn fieldPtr(
1163011611 .ErrorSet => {
1163111612 // TODO resolve inferred error sets
1163211613 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {
11633 const error_set = payload.data;
11634 // TODO this is O(N). I'm putting off solving this until we solve inferred
11635 // error sets at the same time.
11636 const names = error_set.names_ptr[0..error_set.names_len];
11637 for (names) |name| {
11638 if (mem.eql(u8, field_name, name)) {
11639 break :blk name;
11640 }
11614 if (payload.data.names.getEntry(field_name)) |entry| {
11615 break :blk entry.key_ptr.*;
1164111616 }
1164211617 return sema.fail(block, src, "no error named '{s}' in '{}'", .{
1164311618 field_name, child_type,
......@@ -13916,16 +13891,12 @@ fn wrapErrorUnion(
1391613891 if (mem.eql(u8, expected_name, n)) break :ok;
1391713892 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
1391813893 },
13919 .error_set => ok: {
13894 .error_set => {
1392013895 const expected_name = val.castTag(.@"error").?.data.name;
1392113896 const error_set = dest_err_set_ty.castTag(.error_set).?.data;
13922 const names = error_set.names_ptr[0..error_set.names_len];
13923 // TODO this is O(N). I'm putting off solving this until we solve inferred
13924 // error sets at the same time.
13925 for (names) |name| {
13926 if (mem.eql(u8, expected_name, name)) break :ok;
13897 if (!error_set.names.contains(expected_name)) {
13898 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
1392713899 }
13928 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
1392913900 },
1393013901 .error_set_inferred => ok: {
1393113902 const err_set_payload = dest_err_set_ty.castTag(.error_set_inferred).?.data;
src/type.zig+9-8
......@@ -904,10 +904,11 @@ pub const Type = extern union {
904904 });
905905 },
906906 .error_set_merged => {
907 const names = self.castTag(.error_set_merged).?.data;
908 const duped_names = try allocator.alloc([]const u8, names.len);
909 for (duped_names) |*name, i| {
910 name.* = try allocator.dupe(u8, names[i]);
907 const names = self.castTag(.error_set_merged).?.data.keys();
908 var duped_names = Module.ErrorSet.NameMap{};
909 try duped_names.ensureTotalCapacity(allocator, names.len);
910 for (names) |name| {
911 duped_names.putAssumeCapacityNoClobber(name, .{});
911912 }
912913 return Tag.error_set_merged.create(allocator, duped_names);
913914 },
......@@ -1206,7 +1207,7 @@ pub const Type = extern union {
12061207 return writer.print("(inferred error set of {s})", .{func.owner_decl.name});
12071208 },
12081209 .error_set_merged => {
1209 const names = ty.castTag(.error_set_merged).?.data;
1210 const names = ty.castTag(.error_set_merged).?.data.keys();
12101211 try writer.writeAll("error{");
12111212 for (names) |name, i| {
12121213 if (i != 0) try writer.writeByte(',');
......@@ -4148,7 +4149,7 @@ pub const Type = extern union {
41484149 pub const base_tag = Tag.error_set_merged;
41494150
41504151 base: Payload = Payload{ .tag = base_tag },
4151 data: []const []const u8,
4152 data: Module.ErrorSet.NameMap,
41524153 };
41534154
41544155 pub const ErrorSetInferred = struct {
......@@ -4168,7 +4169,7 @@ pub const Type = extern union {
41684169 pub fn addErrorSet(self: *Data, gpa: Allocator, err_set_ty: Type) !void {
41694170 switch (err_set_ty.tag()) {
41704171 .error_set => {
4171 const names = err_set_ty.castTag(.error_set).?.data.names();
4172 const names = err_set_ty.castTag(.error_set).?.data.names.keys();
41724173 for (names) |name| {
41734174 try self.map.put(gpa, name, {});
41744175 }
......@@ -4187,7 +4188,7 @@ pub const Type = extern union {
41874188 }
41884189 },
41894190 .error_set_merged => {
4190 const names = err_set_ty.castTag(.error_set_merged).?.data;
4191 const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
41914192 for (names) |name| {
41924193 try self.map.put(gpa, name, {});
41934194 }