| ... | ... | @@ -2025,15 +2025,22 @@ fn zirErrorSetDecl( |
| 2025 | 2025 | }, type_name); |
| 2026 | 2026 | new_decl.owns_tv = true; |
| 2027 | 2027 | 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 | } |
| 2031 | 2039 | } |
| 2032 | 2040 | error_set.* = .{ |
| 2033 | 2041 | .owner_decl = new_decl, |
| 2034 | 2042 | .node_offset = inst_data.src_node, |
| 2035 | | .names_ptr = names.ptr, |
| 2036 | | .names_len = @intCast(u32, names.len), |
| 2043 | .names = names, |
| 2037 | 2044 | }; |
| 2038 | 2045 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2039 | 2046 | return sema.analyzeDeclVal(block, src, new_decl); |
| ... | ... | @@ -4556,63 +4563,43 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 4556 | 4563 | return Air.Inst.Ref.anyerror_type; |
| 4557 | 4564 | } |
| 4558 | 4565 | // 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; |
| 4579 | 4571 | }, |
| 4572 | .error_set_merged => lhs_ty.castTag(.error_set_merged).?.data.keys(), |
| 4573 | .error_set => lhs_ty.castTag(.error_set).?.data.names.keys(), |
| 4580 | 4574 | 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; |
| 4599 | 4581 | }, |
| 4582 | .error_set_merged => rhs_ty.castTag(.error_set_merged).?.data.keys(), |
| 4583 | .error_set => rhs_ty.castTag(.error_set).?.data.names.keys(), |
| 4600 | 4584 | else => unreachable, |
| 4601 | | } |
| 4585 | }; |
| 4602 | 4586 | |
| 4603 | 4587 | // TODO do we really want to create a Decl for this? |
| 4604 | 4588 | // The reason we do it right now is for memory management. |
| 4605 | 4589 | var anon_decl = try block.startAnonDecl(); |
| 4606 | 4590 | defer anon_decl.deinit(); |
| 4607 | 4591 | |
| 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, {}); |
| 4613 | 4600 | } |
| 4614 | 4601 | |
| 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); |
| 4616 | 4603 | const err_set_decl = try anon_decl.finish( |
| 4617 | 4604 | Type.type, |
| 4618 | 4605 | try Value.Tag.ty.create(anon_decl.arena(), err_set_ty), |
| ... | ... | @@ -11425,14 +11412,8 @@ fn fieldVal( |
| 11425 | 11412 | switch (child_type.zigTypeTag()) { |
| 11426 | 11413 | .ErrorSet => { |
| 11427 | 11414 | 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.*; |
| 11436 | 11417 | } |
| 11437 | 11418 | return sema.fail(block, src, "no error named '{s}' in '{}'", .{ |
| 11438 | 11419 | field_name, child_type, |
| ... | ... | @@ -11630,14 +11611,8 @@ fn fieldPtr( |
| 11630 | 11611 | .ErrorSet => { |
| 11631 | 11612 | // TODO resolve inferred error sets |
| 11632 | 11613 | 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.*; |
| 11641 | 11616 | } |
| 11642 | 11617 | return sema.fail(block, src, "no error named '{s}' in '{}'", .{ |
| 11643 | 11618 | field_name, child_type, |
| ... | ... | @@ -13916,16 +13891,12 @@ fn wrapErrorUnion( |
| 13916 | 13891 | if (mem.eql(u8, expected_name, n)) break :ok; |
| 13917 | 13892 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); |
| 13918 | 13893 | }, |
| 13919 | | .error_set => ok: { |
| 13894 | .error_set => { |
| 13920 | 13895 | const expected_name = val.castTag(.@"error").?.data.name; |
| 13921 | 13896 | 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); |
| 13927 | 13899 | } |
| 13928 | | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); |
| 13929 | 13900 | }, |
| 13930 | 13901 | .error_set_inferred => ok: { |
| 13931 | 13902 | const err_set_payload = dest_err_set_ty.castTag(.error_set_inferred).?.data; |