authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-28 23:15:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-28 23:15:58-07:00
log4763fd1a41bc5f6bb59b5c3c079069b84f19305a
treea4f38b1e2150b5d2a88c66d2d96c23b9dd39775c
parent5e2e7675d53c4258a21d014a09f2a6fdae64b433

Sema: clean up peer resolution of errors

* Fix compile error for `zirErrorUnionType`. * Convert zirMergeErrorSets logic to call `Type.errorSetMerge`. It does not need to create a Decl as the TODO comment hinted. * Extract out a function called `resolveInferredErrorSetTy`. * Rework `resolvePeerTypes` with respect to error unions and error sets. This is a less complex implementation that passes all the same tests and uses many fewer lines of code by taking advantage of the function `coerceInMemoryAllowedErrorSets`. - Always merge error sets in the order that makes sense, even when that means `@typeInfo` incompatibility with stage1. * `Type.errorSetMerge` no longer overallocates. * Don't skip passing tests.

4 files changed, 146 insertions(+), 310 deletions(-)

src/Sema.zig+107-258
......@@ -5141,15 +5141,15 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
51415141 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
51425142 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
51435143 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
5144 const error_union = try sema.resolveType(block, lhs_src, extra.lhs);
5144 const error_set = try sema.resolveType(block, lhs_src, extra.lhs);
51455145 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
51465146
5147 if (error_union.zigTypeTag() != .ErrorSet) {
5147 if (error_set.zigTypeTag() != .ErrorSet) {
51485148 return sema.fail(block, lhs_src, "expected error set type, found {}", .{
5149 error_union.elemType(),
5149 error_set,
51505150 });
51515151 }
5152 const err_union_ty = try Module.errorUnionType(sema.arena, error_union, payload);
5152 const err_union_ty = try Module.errorUnionType(sema.arena, error_set, payload);
51535153 return sema.addType(err_union_ty);
51545154}
51555155
......@@ -5281,31 +5281,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
52815281 }
52825282 }
52835283
5284 // Resolve both error sets now.
5285 const lhs_names = lhs_ty.errorSetNames();
5286 const rhs_names = rhs_ty.errorSetNames();
5287
5288 // TODO do we really want to create a Decl for this?
5289 // The reason we do it right now is for memory management.
5290 var anon_decl = try block.startAnonDecl(src);
5291 defer anon_decl.deinit();
5292
5293 var names = Module.ErrorSet.NameMap{};
5294 // TODO: Guess is an upper bound, but maybe this needs to be reduced by computing the exact size first.
5295 try names.ensureUnusedCapacity(anon_decl.arena(), @intCast(u32, lhs_names.len + rhs_names.len));
5296 for (lhs_names) |name| {
5297 names.putAssumeCapacityNoClobber(name, {});
5298 }
5299 for (rhs_names) |name| {
5300 names.putAssumeCapacity(name, {});
5301 }
5302
5303 const err_set_ty = try Type.Tag.error_set_merged.create(anon_decl.arena(), names);
5304 const err_set_decl = try anon_decl.finish(
5305 Type.type,
5306 try Value.Tag.ty.create(anon_decl.arena(), err_set_ty),
5307 );
5308 try sema.mod.declareDeclDependency(sema.owner_decl, err_set_decl);
5284 const err_set_ty = try lhs_ty.errorSetMerge(sema.arena, rhs_ty);
53095285 return sema.addType(err_set_ty);
53105286}
53115287
......@@ -6858,9 +6834,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
68586834 }
68596835 }
68606836
6861 if (operand_ty.castTag(.error_set_inferred)) |inferred| {
6862 try sema.resolveInferredErrorSet(inferred.data);
6863 }
6837 try sema.resolveInferredErrorSetTy(operand_ty);
68646838
68656839 if (operand_ty.isAnyError()) {
68666840 if (special_prong != .@"else") {
......@@ -10361,9 +10335,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1036110335 };
1036210336
1036310337 // If the error set is inferred it has to be resolved at this point
10364 if (ty.castTag(.error_set_inferred)) |payload| {
10365 try sema.resolveInferredErrorSet(payload.data);
10366 }
10338 try sema.resolveInferredErrorSetTy(ty);
1036710339
1036810340 // Build our list of Error values
1036910341 // Optional value is only null if anyerror
......@@ -17610,32 +17582,25 @@ fn resolvePeerTypes(
1761017582 const target = sema.mod.getTarget();
1761117583
1761217584 var chosen = instructions[0];
17613 var err_set_ty: ?Type = blk: {
17614 const chosen_ty = sema.typeOf(chosen);
17615 const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison();
17616 if (chosen_ty_tag != .ErrorSet)
17617 break :blk null;
17618
17619 // If our chosen type is inferred, we have to resolve it now.
17620 if (chosen_ty.castTag(.error_set_inferred)) |inferred| {
17621 try sema.resolveInferredErrorSet(inferred.data);
17622 }
17623
17624 break :blk chosen_ty;
17625 };
17626
17585 // If this is non-null then it does the following thing, depending on the chosen zigTypeTag().
17586 // * ErrorSet: this is an override
17587 // * ErrorUnion: this is an override of the error set only
17588 // * other: at the end we make an ErrorUnion with the other thing and this
17589 var err_set_ty: ?Type = null;
1762717590 var any_are_null = false;
17628 var make_the_slice_const = false;
17591 var seen_const = false;
1762917592 var convert_to_slice = false;
1763017593 var chosen_i: usize = 0;
1763117594 for (instructions[1..]) |candidate, candidate_i| {
1763217595 const candidate_ty = sema.typeOf(candidate);
1763317596 const chosen_ty = sema.typeOf(chosen);
17597
17598 const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison();
17599 const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison();
17600
1763417601 if (candidate_ty.eql(chosen_ty))
1763517602 continue;
1763617603
17637 const candidate_ty_tag = candidate_ty.zigTypeTag();
17638 const chosen_ty_tag = chosen_ty.zigTypeTag();
1763917604 switch (candidate_ty_tag) {
1764017605 .NoReturn, .Undefined => continue,
1764117606
......@@ -17713,131 +17678,70 @@ fn resolvePeerTypes(
1771317678 },
1771417679 else => {},
1771517680 },
17716 .ErrorSet => {
17717 if (chosen_ty_tag == .ErrorSet) {
17718 assert(err_set_ty != null);
17719
17720 // If chosen type is anyerror, then we can use the prev type
17721 if (err_set_ty.?.isAnyError()) continue;
17722
17723 // At this point, we must resolve any inferred error sets
17724 if (candidate_ty.castTag(.error_set_inferred)) |inferred| {
17725 try sema.resolveInferredErrorSet(inferred.data);
17726 }
17727
17728 // If candidate is anyerror then we use it because it
17729 // is trivially a supserset of previous error set
17730 if (candidate_ty.isAnyError()) {
17731 err_set_ty = candidate_ty;
17732 chosen = candidate;
17733 chosen_i = candidate_i + 1;
17734 continue;
17735 }
17736
17681 .ErrorSet => switch (chosen_ty_tag) {
17682 .ErrorSet => {
1773717683 // If chosen is superset of candidate, keep it.
1773817684 // If candidate is superset of chosen, switch it.
1773917685 // If neither is a superset, merge errors.
17740 for (candidate_ty.errorSetNames()) |name| {
17741 if (!err_set_ty.?.errorSetHasField(name)) {
17742 break;
17743 }
17744 } else continue;
17686 const chosen_set_ty = err_set_ty orelse chosen_ty;
1774517687
17746 for (err_set_ty.?.errorSetNames()) |name| {
17747 if (!candidate_ty.errorSetHasField(name)) {
17748 break;
17749 }
17750 } else {
17751 // Swap to candidate
17752 err_set_ty = candidate_ty;
17688 if (.ok == try sema.coerceInMemoryAllowedErrorSets(chosen_set_ty, candidate_ty)) {
17689 continue;
17690 }
17691 if (.ok == try sema.coerceInMemoryAllowedErrorSets(candidate_ty, chosen_set_ty)) {
17692 err_set_ty = null;
1775317693 chosen = candidate;
1775417694 chosen_i = candidate_i + 1;
1775517695 continue;
1775617696 }
1775717697
17758 // Merge errors
17759 err_set_ty = try candidate_ty.errorSetMerge(sema.arena, err_set_ty.?);
17760 chosen = candidate;
17761 chosen_i = candidate_i + 1;
17698 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
1776217699 continue;
17763 }
17700 },
17701 .ErrorUnion => {
17702 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet();
1776417703
17765 // At this point, we must resolve any inferred error sets
17766 if (candidate_ty.castTag(.error_set_inferred)) |inferred| {
17767 try sema.resolveInferredErrorSet(inferred.data);
17768 }
17704 if (.ok == try sema.coerceInMemoryAllowedErrorSets(chosen_set_ty, candidate_ty)) {
17705 continue;
17706 }
17707 if (.ok == try sema.coerceInMemoryAllowedErrorSets(candidate_ty, chosen_set_ty)) {
17708 err_set_ty = candidate_ty;
17709 continue;
17710 }
1776917711
17770 // If anything is anyerror, we use anyerror always
17771 if (candidate_ty.isAnyError()) {
17772 err_set_ty = candidate_ty;
17712 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
1777317713 continue;
17774 }
17775 if (err_set_ty) |ty|
17776 if (ty.isAnyError()) continue;
17777
17778 if (err_set_ty == null) {
17779 // Error unions are lazy, we're forced to resolve now.
17780 // Otherwise, our candidate type cause we've never seen
17781 // error sets up to this point
17782 if (chosen_ty_tag == .ErrorUnion) {
17783 err_set_ty = chosen_ty.errorUnionSet();
17784
17785 if (err_set_ty.?.castTag(.error_set_inferred)) |inferred| {
17786 try sema.resolveInferredErrorSet(inferred.data);
17714 },
17715 else => {
17716 if (err_set_ty) |chosen_set_ty| {
17717 if (.ok == try sema.coerceInMemoryAllowedErrorSets(chosen_set_ty, candidate_ty)) {
17718 continue;
17719 }
17720 if (.ok == try sema.coerceInMemoryAllowedErrorSets(candidate_ty, chosen_set_ty)) {
17721 err_set_ty = candidate_ty;
17722 continue;
1778717723 }
1778817724
17789 if (err_set_ty.?.isAnyError()) continue;
17725 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
17726 continue;
1779017727 } else {
1779117728 err_set_ty = candidate_ty;
1779217729 continue;
1779317730 }
17794 }
17795
17796 // If previous is superset, keep the previous
17797 for (candidate_ty.errorSetNames()) |name| {
17798 if (!err_set_ty.?.errorSetHasField(name)) {
17799 break;
17800 }
17801 } else continue;
17802
17803 // Merge
17804 err_set_ty = try err_set_ty.?.errorSetMerge(sema.arena, candidate_ty);
17805 continue;
17731 },
1780617732 },
1780717733 .ErrorUnion => switch (chosen_ty_tag) {
1780817734 .ErrorSet => {
17809 if (err_set_ty.?.isAnyError()) {
17810 chosen = candidate;
17811 chosen_i = candidate_i + 1;
17812 continue;
17813 }
17814
17815 const eu_set_ty = candidate_ty.errorUnionSet();
17816 if (eu_set_ty.castTag(.error_set_inferred)) |inferred| {
17817 try sema.resolveInferredErrorSet(inferred.data);
17818 }
17819 if (eu_set_ty.isAnyError()) {
17820 err_set_ty = eu_set_ty;
17821 chosen = candidate;
17822 chosen_i = candidate_i + 1;
17823 continue;
17824 }
17735 const chosen_set_ty = err_set_ty orelse chosen_ty;
17736 const candidate_set_ty = candidate_ty.errorUnionSet();
1782517737
17826 // If candidate is a superset of the error type, then use it.
17827 for (err_set_ty.?.errorSetNames()) |name| {
17828 if (!eu_set_ty.errorSetHasField(name)) {
17829 break;
17830 }
17738 if (.ok == try sema.coerceInMemoryAllowedErrorSets(chosen_set_ty, candidate_set_ty)) {
17739 err_set_ty = chosen_set_ty;
17740 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(candidate_set_ty, chosen_set_ty)) {
17741 err_set_ty = null;
1783117742 } else {
17832 // Swap to candidate
17833 err_set_ty = eu_set_ty;
17834 chosen = candidate;
17835 chosen_i = candidate_i + 1;
17836 continue;
17743 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_set_ty);
1783717744 }
17838
17839 // Not a superset, create merged error set
17840 err_set_ty = try eu_set_ty.errorSetMerge(sema.arena, err_set_ty.?);
1784117745 chosen = candidate;
1784217746 chosen_i = candidate_i + 1;
1784317747 continue;
......@@ -17859,104 +17763,35 @@ fn resolvePeerTypes(
1785917763 chosen_i = candidate_i + 1;
1786017764 }
1786117765
17862 const chosen_set_ty = chosen_ty.errorUnionSet();
17766 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet();
1786317767 const candidate_set_ty = chosen_ty.errorUnionSet();
1786417768
17865 // If our error sets match already, then we are done.
17866 if (chosen_set_ty.eql(candidate_set_ty)) continue;
17867
17868 // They don't match, so we need to figure out if we
17869 // need to merge them, use the superset, etc. This
17870 // requires resolution.
17871 if (chosen_set_ty.castTag(.error_set_inferred)) |inferred| {
17872 try sema.resolveInferredErrorSet(inferred.data);
17873 }
17874 if (candidate_set_ty.castTag(.error_set_inferred)) |inferred| {
17875 try sema.resolveInferredErrorSet(inferred.data);
17876 }
17877
17878 if (chosen_set_ty.isAnyError()) {
17769 if (.ok == try sema.coerceInMemoryAllowedErrorSets(chosen_set_ty, candidate_set_ty)) {
1787917770 err_set_ty = chosen_set_ty;
17880 continue;
17881 }
17882
17883 if (candidate_set_ty.isAnyError()) {
17771 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(candidate_set_ty, chosen_set_ty)) {
1788417772 err_set_ty = candidate_set_ty;
17885 continue;
17886 }
17887
17888 if (err_set_ty == null) err_set_ty = chosen_set_ty;
17889
17890 // If the previous error set type is a superset, we're done.
17891 for (candidate_set_ty.errorSetNames()) |name| {
17892 if (!chosen_set_ty.errorSetHasField(name)) {
17893 break;
17894 }
17895 } else continue;
17896
17897 for (chosen_set_ty.errorSetNames()) |name| {
17898 if (!candidate_set_ty.errorSetHasField(name)) {
17899 break;
17900 }
1790117773 } else {
17902 err_set_ty = candidate_ty;
17903 continue;
17774 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_set_ty);
1790417775 }
17905
17906 // Merge errors
17907 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
1790817776 continue;
1790917777 }
1791017778 },
1791117779
17912 .Pointer => {
17913 const payload_ty = candidate_ty.errorUnionPayload();
17914 if (chosen_ty.ptrSize() == .One and
17915 chosen_ty.childType().zigTypeTag() == .Array and
17916 payload_ty.isSlice())
17917 {
17918 const chosen_child_ty = chosen_ty.childType();
17919 const chosen_elem_ty = chosen_child_ty.elemType2();
17920 const candidate_elem_ty = payload_ty.elemType2();
17921 if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) {
17922 chosen = candidate;
17923 chosen_i = candidate_i + 1;
17924
17925 convert_to_slice = false; // it already is a slice
17926
17927 // If the prev pointer is const then we need to const
17928 if (chosen_child_ty.isConstPtr())
17929 make_the_slice_const = true;
17930
17931 continue;
17932 }
17933 }
17934 },
17935
1793617780 else => {
17937 // Chosen coercing into payload type
17938 // Then merge error sets (if any)
17939 const payload_ty = candidate_ty.errorUnionPayload();
17940 if ((try sema.coerceInMemoryAllowed(block, payload_ty, chosen_ty, false, target, src, src)) == .ok) {
17941 chosen = candidate;
17942 chosen_i = candidate_i + 1;
17943
17944 if (err_set_ty) |ty| {
17945 const cand_set_ty = candidate_ty.errorUnionSet();
17946 if (cand_set_ty.castTag(.error_set_inferred)) |inferred| {
17947 try sema.resolveInferredErrorSet(inferred.data);
17948 }
17949 if (cand_set_ty.isAnyError()) {
17950 err_set_ty = cand_set_ty;
17951 continue;
17952 }
17953 if (ty.isAnyError()) continue;
17954
17955 err_set_ty = try err_set_ty.?.errorSetMerge(sema.arena, cand_set_ty);
17781 if (err_set_ty) |chosen_set_ty| {
17782 const candidate_set_ty = candidate_ty.errorUnionSet();
17783 if (.ok == try sema.coerceInMemoryAllowedErrorSets(chosen_set_ty, candidate_set_ty)) {
17784 err_set_ty = chosen_set_ty;
17785 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(candidate_set_ty, chosen_set_ty)) {
17786 err_set_ty = null;
17787 } else {
17788 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_set_ty);
1795617789 }
17957
17958 continue;
1795917790 }
17791 seen_const = seen_const or chosen_ty.isConstPtr();
17792 chosen = candidate;
17793 chosen_i = candidate_i + 1;
17794 continue;
1796017795 },
1796117796 },
1796217797 .Pointer => {
......@@ -17983,7 +17818,7 @@ fn resolvePeerTypes(
1798317818 convert_to_slice = false;
1798417819
1798517820 if (chosen_ty.childType().isConstPtr() and !candidate_ty.childType().isConstPtr())
17986 make_the_slice_const = true;
17821 seen_const = true;
1798717822
1798817823 continue;
1798917824 }
......@@ -17995,7 +17830,7 @@ fn resolvePeerTypes(
1799517830 chosen_ty.ptrSize() == .Many)
1799617831 {
1799717832 if (candidate_ty.childType().isConstPtr() and !chosen_ty.childType().isConstPtr())
17998 make_the_slice_const = true;
17833 seen_const = true;
1799917834
1800017835 continue;
1800117836 }
......@@ -18016,7 +17851,7 @@ fn resolvePeerTypes(
1801617851
1801717852 // If the pointer is const then we need to const
1801817853 if (candidate_ty.childType().isConstPtr())
18019 make_the_slice_const = true;
17854 seen_const = true;
1802017855
1802117856 continue;
1802217857 }
......@@ -18039,7 +17874,7 @@ fn resolvePeerTypes(
1803917874
1804017875 // If the prev pointer is const then we need to const
1804117876 if (chosen_child_ty.isConstPtr())
18042 make_the_slice_const = true;
17877 seen_const = true;
1804317878
1804417879 continue;
1804517880 }
......@@ -18075,7 +17910,7 @@ fn resolvePeerTypes(
1807517910 // If one of the pointers is to const data, the slice
1807617911 // must also be const.
1807717912 if (candidate_child_ty.isConstPtr() or chosen_child_ty.isConstPtr())
18078 make_the_slice_const = true;
17913 seen_const = true;
1807917914
1808017915 continue;
1808117916 }
......@@ -18186,39 +18021,47 @@ fn resolvePeerTypes(
1818618021 var info = chosen_ty.ptrInfo();
1818718022 info.data.sentinel = chosen_child_ty.sentinel();
1818818023 info.data.size = .Slice;
18189 info.data.mutable = chosen_child_ty.isConstPtr() or make_the_slice_const;
18024 info.data.mutable = seen_const or chosen_child_ty.isConstPtr();
1819018025 info.data.pointee_type = switch (chosen_child_ty.tag()) {
1819118026 .array => chosen_child_ty.elemType2(),
1819218027 .array_u8, .array_u8_sentinel_0 => Type.initTag(.u8),
1819318028 else => unreachable,
1819418029 };
1819518030
18196 return Type.ptr(sema.arena, target, info.data);
18031 const new_ptr_ty = try Type.ptr(sema.arena, target, info.data);
18032 const set_ty = err_set_ty orelse return new_ptr_ty;
18033 return try Module.errorUnionType(sema.arena, set_ty, new_ptr_ty);
1819718034 }
1819818035
18199 if (make_the_slice_const) {
18036 if (seen_const) {
1820018037 // turn []T => []const T
18201 var info = chosen_ty.ptrInfo();
18202 info.data.mutable = false;
18203 return Type.ptr(sema.arena, target, info.data);
18038 switch (chosen_ty.zigTypeTag()) {
18039 .ErrorUnion => {
18040 const ptr_ty = chosen_ty.errorUnionPayload();
18041 var info = ptr_ty.ptrInfo();
18042 info.data.mutable = false;
18043 const new_ptr_ty = try Type.ptr(sema.arena, target, info.data);
18044 const set_ty = err_set_ty orelse chosen_ty.errorUnionSet();
18045 return try Module.errorUnionType(sema.arena, set_ty, new_ptr_ty);
18046 },
18047 .Pointer => {
18048 var info = chosen_ty.ptrInfo();
18049 info.data.mutable = false;
18050 const new_ptr_ty = try Type.ptr(sema.arena, target, info.data);
18051 const set_ty = err_set_ty orelse return new_ptr_ty;
18052 return try Module.errorUnionType(sema.arena, set_ty, new_ptr_ty);
18053 },
18054 else => return chosen_ty,
18055 }
1820418056 }
1820518057
1820618058 if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) {
1820718059 .ErrorSet => return ty,
18208
1820918060 .ErrorUnion => {
1821018061 const payload_ty = chosen_ty.errorUnionPayload();
1821118062 return try Module.errorUnionType(sema.arena, ty, payload_ty);
1821218063 },
18213
18214 .ComptimeInt, .ComptimeFloat => return sema.fail(block, src, "unable to make error union out of number literal", .{}),
18215
18216 .Null => return sema.fail(block, src, "unable to make error union out of null literal", .{}),
18217
18218 else => {
18219 // Create error union of our error set and the chosen type
18220 return try Module.errorUnionType(sema.arena, ty, chosen_ty);
18221 },
18064 else => return try Module.errorUnionType(sema.arena, ty, chosen_ty),
1822218065 };
1822318066
1822418067 return chosen_ty;
......@@ -18507,6 +18350,12 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE
1850718350 inferred_error_set.is_resolved = true;
1850818351}
1850918352
18353fn resolveInferredErrorSetTy(sema: *Sema, ty: Type) CompileError!void {
18354 if (ty.castTag(.error_set_inferred)) |inferred| {
18355 try sema.resolveInferredErrorSet(inferred.data);
18356 }
18357}
18358
1851018359fn semaStructFields(
1851118360 mod: *Module,
1851218361 struct_obj: *Module.Struct,
src/type.zig+8-8
......@@ -4216,18 +4216,18 @@ pub const Type = extern union {
42164216 };
42174217 }
42184218
4219 /// Merge ty with ty2.
4220 /// Asserts that ty and ty2 are both error sets and are resolved.
4221 pub fn errorSetMerge(ty: Type, arena: Allocator, ty2: Type) !Type {
4222 const lhs_names = ty.errorSetNames();
4223 const rhs_names = ty2.errorSetNames();
4224 var names = Module.ErrorSet.NameMap{};
4225 try names.ensureUnusedCapacity(arena, @intCast(u32, lhs_names.len + rhs_names.len));
4219 /// Merge lhs with rhs.
4220 /// Asserts that lhs and rhs are both error sets and are resolved.
4221 pub fn errorSetMerge(lhs: Type, arena: Allocator, rhs: Type) !Type {
4222 const lhs_names = lhs.errorSetNames();
4223 const rhs_names = rhs.errorSetNames();
4224 var names: Module.ErrorSet.NameMap = .{};
4225 try names.ensureUnusedCapacity(arena, lhs_names.len);
42264226 for (lhs_names) |name| {
42274227 names.putAssumeCapacityNoClobber(name, {});
42284228 }
42294229 for (rhs_names) |name| {
4230 names.putAssumeCapacity(name, {});
4230 try names.put(arena, name, {});
42314231 }
42324232
42334233 return try Tag.error_set_merged.create(arena, names);
test/behavior/cast.zig+30-40
......@@ -591,11 +591,10 @@ test "@floatCast cast down" {
591591}
592592
593593test "peer type resolution: unreachable, error set, unreachable" {
594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
595 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
597 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
598594 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
597 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
599598
600599 const Error = error{
601600 FileDescriptorAlreadyPresentInSet,
......@@ -620,11 +619,6 @@ test "peer type resolution: unreachable, error set, unreachable" {
620619}
621620
622621test "peer cast: error set any anyerror" {
623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
624 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
626 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
627
628622 const a: error{ One, Two } = undefined;
629623 const b: anyerror = undefined;
630624 try expect(@TypeOf(a, b) == anyerror);
......@@ -632,11 +626,9 @@ test "peer cast: error set any anyerror" {
632626}
633627
634628test "peer type resolution: error set supersets" {
635 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
636 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
637 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
638629 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
639 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
630 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
640632
641633 const a: error{ One, Two } = undefined;
642634 const b: error{One} = undefined;
......@@ -663,25 +655,26 @@ test "peer type resolution: error set supersets" {
663655}
664656
665657test "peer type resolution: disjoint error sets" {
666 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
667 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
668 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
658 if (builtin.zig_backend == .stage1) {
659 // stage1 gets the order of the error names wrong after merging the sets.
660 return error.SkipZigTest;
661 }
662
669663 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
670 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
665 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
671666
672667 const a: error{ One, Two } = undefined;
673668 const b: error{Three} = undefined;
674669
675 // note: order of error set made to match stage1 during stage2 dev
676
677670 {
678671 const ty = @TypeOf(a, b);
679672 const error_set_info = @typeInfo(ty);
680673 try expect(error_set_info == .ErrorSet);
681674 try expect(error_set_info.ErrorSet.?.len == 3);
682 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "Three"));
683 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "One"));
684 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
675 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
676 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
677 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
685678 }
686679
687680 {
......@@ -689,24 +682,25 @@ test "peer type resolution: disjoint error sets" {
689682 const error_set_info = @typeInfo(ty);
690683 try expect(error_set_info == .ErrorSet);
691684 try expect(error_set_info.ErrorSet.?.len == 3);
692 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
693 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
694 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
685 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "Three"));
686 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "One"));
687 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
695688 }
696689}
697690
698691test "peer type resolution: error union and error set" {
699 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
700 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
701 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
692 if (builtin.zig_backend == .stage1) {
693 // stage1 gets the order of the error names wrong after merging the sets.
694 return error.SkipZigTest;
695 }
696
702697 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
703 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
698 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
699 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
704700
705701 const a: error{Three} = undefined;
706702 const b: error{ One, Two }!u32 = undefined;
707703
708 // note: order of error set made to match stage1 during stage2 dev
709
710704 {
711705 const ty = @TypeOf(a, b);
712706 const info = @typeInfo(ty);
......@@ -714,9 +708,9 @@ test "peer type resolution: error union and error set" {
714708
715709 const error_set_info = @typeInfo(info.ErrorUnion.error_set);
716710 try expect(error_set_info.ErrorSet.?.len == 3);
717 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
718 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
719 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
711 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "Three"));
712 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "One"));
713 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
720714 }
721715
722716 {
......@@ -733,17 +727,13 @@ test "peer type resolution: error union and error set" {
733727}
734728
735729test "peer type resolution: error union after non-error" {
736 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
737 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
738 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
739730 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
740 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
741733
742734 const a: u32 = undefined;
743735 const b: error{ One, Two }!u32 = undefined;
744736
745 // note: order of error set made to match stage1 during stage2 dev
746
747737 {
748738 const ty = @TypeOf(a, b);
749739 const info = @typeInfo(ty);
test/behavior/error.zig+1-4
......@@ -264,11 +264,8 @@ fn testErrToIntWithOnePossibleValue(
264264}
265265
266266test "error union peer type resolution" {
267 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
269267 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
270 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
271 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
268 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
272269
273270 try testErrorUnionPeerTypeResolution(1);
274271}