authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-10 14:11:59+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-11 23:49:33+03:00
log0333ff4476d0132a2397122dcab964de7fc0f2d3
tree8032dc588ab76313580feec71e07077ab1209960
parent488e1e5f51905485f9db37038e74bdea31ebd16e

stage2: make `error{}` the same size as `anyerror`

Having `error{}` be a zero bit type causes issues when it interracts with empty inferred error sets which are the same size as `anyerror`.

11 files changed, 123 insertions(+), 476 deletions(-)

lib/std/compress/deflate/compressor_test.zig-2
...@@ -179,7 +179,6 @@ test "deflate/inflate" {...@@ -179,7 +179,6 @@ test "deflate/inflate" {
179}179}
180180
181test "very long sparse chunk" {181test "very long sparse chunk" {
182 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
183 // A SparseReader returns a stream consisting of 0s ending with 65,536 (1<<16) 1s.182 // A SparseReader returns a stream consisting of 0s ending with 65,536 (1<<16) 1s.
184 // This tests missing hash references in a very large input.183 // This tests missing hash references in a very large input.
185 const SparseReader = struct {184 const SparseReader = struct {
...@@ -377,7 +376,6 @@ test "compressor dictionary" {...@@ -377,7 +376,6 @@ test "compressor dictionary" {
377// Update the hash for best_speed only if d.index < d.maxInsertIndex376// Update the hash for best_speed only if d.index < d.maxInsertIndex
378// See https://golang.org/issue/2508377// See https://golang.org/issue/2508
379test "Go non-regression test for 2508" {378test "Go non-regression test for 2508" {
380 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
381 var comp = try compressor(379 var comp = try compressor(
382 testing.allocator,380 testing.allocator,
383 io.null_writer,381 io.null_writer,
src/Sema.zig+17-42
...@@ -6182,6 +6182,17 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -6182,6 +6182,17 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
6182 }6182 }
6183 }6183 }
61846184
6185 const op_ty = sema.typeOf(op);
6186 try sema.resolveInferredErrorSetTy(block, src, op_ty);
6187 if (!op_ty.isAnyError()) {
6188 const names = op_ty.errorSetNames();
6189 switch (names.len) {
6190 0 => return sema.addConstant(result_ty, Value.zero),
6191 1 => return sema.addIntUnsigned(result_ty, sema.mod.global_error_set.get(names[0]).?),
6192 else => {},
6193 }
6194 }
6195
6185 try sema.requireRuntimeBlock(block, src);6196 try sema.requireRuntimeBlock(block, src);
6186 return block.addBitCast(result_ty, op_coerced);6197 return block.addBitCast(result_ty, op_coerced);
6187}6198}
...@@ -6560,7 +6571,7 @@ fn analyzeErrUnionPayload(...@@ -6560,7 +6571,7 @@ fn analyzeErrUnionPayload(
65606571
6561 // If the error set has no fields then no safety check is needed.6572 // If the error set has no fields then no safety check is needed.
6562 if (safety_check and block.wantSafety() and6573 if (safety_check and block.wantSafety() and
6563 err_union_ty.errorUnionSet().errorSetCardinality() != .zero)6574 !err_union_ty.errorUnionSet().errorSetIsEmpty())
6564 {6575 {
6565 try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);6576 try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
6566 }6577 }
...@@ -6646,7 +6657,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -6646,7 +6657,7 @@ fn analyzeErrUnionPayloadPtr(
66466657
6647 // If the error set has no fields then no safety check is needed.6658 // If the error set has no fields then no safety check is needed.
6648 if (safety_check and block.wantSafety() and6659 if (safety_check and block.wantSafety() and
6649 err_union_ty.errorUnionSet().errorSetCardinality() != .zero)6660 !err_union_ty.errorUnionSet().errorSetIsEmpty())
6650 {6661 {
6651 try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);6662 try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
6652 }6663 }
...@@ -24231,6 +24242,10 @@ pub fn typeHasOnePossibleValue(...@@ -24231,6 +24242,10 @@ pub fn typeHasOnePossibleValue(
24231 .bool,24242 .bool,
24232 .type,24243 .type,
24233 .anyerror,24244 .anyerror,
24245 .error_set_single,
24246 .error_set,
24247 .error_set_merged,
24248 .error_union,
24234 .fn_noreturn_no_args,24249 .fn_noreturn_no_args,
24235 .fn_void_no_args,24250 .fn_void_no_args,
24236 .fn_naked_noreturn_no_args,24251 .fn_naked_noreturn_no_args,
...@@ -24287,46 +24302,6 @@ pub fn typeHasOnePossibleValue(...@@ -24287,46 +24302,6 @@ pub fn typeHasOnePossibleValue(
24287 }24302 }
24288 },24303 },
2428924304
24290 .error_union => {
24291 const error_ty = ty.errorUnionSet();
24292 switch (error_ty.errorSetCardinality()) {
24293 .zero => {
24294 const payload_ty = ty.errorUnionPayload();
24295 if (try typeHasOnePossibleValue(sema, block, src, payload_ty)) |payload_val| {
24296 return try Value.Tag.eu_payload.create(sema.arena, payload_val);
24297 } else {
24298 return null;
24299 }
24300 },
24301 .one => {
24302 if (ty.errorUnionPayload().isNoReturn()) {
24303 const error_val = (try typeHasOnePossibleValue(sema, block, src, error_ty)).?;
24304 return error_val;
24305 } else {
24306 return null;
24307 }
24308 },
24309 .many => return null,
24310 }
24311 },
24312
24313 .error_set_single => {
24314 const name = ty.castTag(.error_set_single).?.data;
24315 return try Value.Tag.@"error".create(sema.arena, .{ .name = name });
24316 },
24317 .error_set => {
24318 const err_set_obj = ty.castTag(.error_set).?.data;
24319 const names = err_set_obj.names.keys();
24320 if (names.len > 1) return null;
24321 return try Value.Tag.@"error".create(sema.arena, .{ .name = names[0] });
24322 },
24323 .error_set_merged => {
24324 const name_map = ty.castTag(.error_set_merged).?.data;
24325 const names = name_map.keys();
24326 if (names.len > 1) return null;
24327 return try Value.Tag.@"error".create(sema.arena, .{ .name = names[0] });
24328 },
24329
24330 .@"struct" => {24305 .@"struct" => {
24331 const resolved_ty = try sema.resolveTypeFields(block, src, ty);24306 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
24332 const s = resolved_ty.castTag(.@"struct").?.data;24307 const s = resolved_ty.castTag(.@"struct").?.data;
src/arch/aarch64/CodeGen.zig+3-8
...@@ -2277,7 +2277,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -2277,7 +2277,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
2277fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {2277fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
2278 const err_ty = error_union_ty.errorUnionSet();2278 const err_ty = error_union_ty.errorUnionSet();
2279 const payload_ty = error_union_ty.errorUnionPayload();2279 const payload_ty = error_union_ty.errorUnionPayload();
2280 if (err_ty.errorSetCardinality() == .zero) {2280 if (err_ty.errorSetIsEmpty()) {
2281 return MCValue{ .immediate = 0 };2281 return MCValue{ .immediate = 0 };
2282 }2282 }
2283 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2283 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
...@@ -2311,7 +2311,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2311,7 +2311,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2311fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {2311fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
2312 const err_ty = error_union_ty.errorUnionSet();2312 const err_ty = error_union_ty.errorUnionSet();
2313 const payload_ty = error_union_ty.errorUnionPayload();2313 const payload_ty = error_union_ty.errorUnionPayload();
2314 if (err_ty.errorSetCardinality() == .zero) {2314 if (err_ty.errorSetIsEmpty()) {
2315 return error_union_mcv;2315 return error_union_mcv;
2316 }2316 }
2317 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2317 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
...@@ -3590,7 +3590,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3590,7 +3590,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3590 const error_type = ty.errorUnionSet();3590 const error_type = ty.errorUnionSet();
3591 const payload_type = ty.errorUnionPayload();3591 const payload_type = ty.errorUnionPayload();
35923592
3593 if (error_type.errorSetCardinality() == .zero) {3593 if (error_type.errorSetIsEmpty()) {
3594 return MCValue{ .immediate = 0 }; // always false3594 return MCValue{ .immediate = 0 }; // always false
3595 }3595 }
35963596
...@@ -4687,11 +4687,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -4687,11 +4687,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4687 const error_type = typed_value.ty.errorUnionSet();4687 const error_type = typed_value.ty.errorUnionSet();
4688 const payload_type = typed_value.ty.errorUnionPayload();4688 const payload_type = typed_value.ty.errorUnionPayload();
46894689
4690 if (error_type.errorSetCardinality() == .zero) {
4691 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
4692 return self.genTypedValue(.{ .ty = payload_type, .val = payload_val });
4693 }
4694
4695 const is_pl = typed_value.val.errorUnionIsPayload();4690 const is_pl = typed_value.val.errorUnionIsPayload();
46964691
4697 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {4692 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
src/arch/arm/CodeGen.zig+3-9
...@@ -1773,7 +1773,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -1773,7 +1773,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1773fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {1773fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
1774 const err_ty = error_union_ty.errorUnionSet();1774 const err_ty = error_union_ty.errorUnionSet();
1775 const payload_ty = error_union_ty.errorUnionPayload();1775 const payload_ty = error_union_ty.errorUnionPayload();
1776 if (err_ty.errorSetCardinality() == .zero) {1776 if (err_ty.errorSetIsEmpty()) {
1777 return MCValue{ .immediate = 0 };1777 return MCValue{ .immediate = 0 };
1778 }1778 }
1779 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1779 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
...@@ -1810,7 +1810,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1810,7 +1810,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1810fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {1810fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
1811 const err_ty = error_union_ty.errorUnionSet();1811 const err_ty = error_union_ty.errorUnionSet();
1812 const payload_ty = error_union_ty.errorUnionPayload();1812 const payload_ty = error_union_ty.errorUnionPayload();
1813 if (err_ty.errorSetCardinality() == .zero) {1813 if (err_ty.errorSetIsEmpty()) {
1814 return error_union_mcv;1814 return error_union_mcv;
1815 }1815 }
1816 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1816 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
...@@ -3922,7 +3922,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3922,7 +3922,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3922 const error_type = ty.errorUnionSet();3922 const error_type = ty.errorUnionSet();
3923 const error_int_type = Type.initTag(.u16);3923 const error_int_type = Type.initTag(.u16);
39243924
3925 if (error_type.errorSetCardinality() == .zero) {3925 if (error_type.errorSetIsEmpty()) {
3926 return MCValue{ .immediate = 0 }; // always false3926 return MCValue{ .immediate = 0 }; // always false
3927 }3927 }
39283928
...@@ -5368,12 +5368,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -5368,12 +5368,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
5368 .ErrorUnion => {5368 .ErrorUnion => {
5369 const error_type = typed_value.ty.errorUnionSet();5369 const error_type = typed_value.ty.errorUnionSet();
5370 const payload_type = typed_value.ty.errorUnionPayload();5370 const payload_type = typed_value.ty.errorUnionPayload();
5371
5372 if (error_type.errorSetCardinality() == .zero) {
5373 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
5374 return self.genTypedValue(.{ .ty = payload_type, .val = payload_val });
5375 }
5376
5377 const is_pl = typed_value.val.errorUnionIsPayload();5371 const is_pl = typed_value.val.errorUnionIsPayload();
53785372
5379 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {5373 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
src/arch/wasm/CodeGen.zig+19-41
...@@ -1377,11 +1377,7 @@ fn isByRef(ty: Type, target: std.Target) bool {...@@ -1377,11 +1377,7 @@ fn isByRef(ty: Type, target: std.Target) bool {
1377 .Int => return ty.intInfo(target).bits > 64,1377 .Int => return ty.intInfo(target).bits > 64,
1378 .Float => return ty.floatBits(target) > 64,1378 .Float => return ty.floatBits(target) > 64,
1379 .ErrorUnion => {1379 .ErrorUnion => {
1380 const err_ty = ty.errorUnionSet();
1381 const pl_ty = ty.errorUnionPayload();1380 const pl_ty = ty.errorUnionPayload();
1382 if (err_ty.errorSetCardinality() == .zero) {
1383 return isByRef(pl_ty, target);
1384 }
1385 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {1381 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
1386 return false;1382 return false;
1387 }1383 }
...@@ -1816,11 +1812,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -1816,11 +1812,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
1816fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {1812fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {
1817 switch (ty.zigTypeTag()) {1813 switch (ty.zigTypeTag()) {
1818 .ErrorUnion => {1814 .ErrorUnion => {
1819 const err_ty = ty.errorUnionSet();
1820 const pl_ty = ty.errorUnionPayload();1815 const pl_ty = ty.errorUnionPayload();
1821 if (err_ty.errorSetCardinality() == .zero) {
1822 return self.store(lhs, rhs, pl_ty, 0);
1823 }
1824 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {1816 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
1825 return self.store(lhs, rhs, Type.anyerror, 0);1817 return self.store(lhs, rhs, Type.anyerror, 0);
1826 }1818 }
...@@ -2353,10 +2345,6 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {...@@ -2353,10 +2345,6 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
2353 },2345 },
2354 .ErrorUnion => {2346 .ErrorUnion => {
2355 const error_type = ty.errorUnionSet();2347 const error_type = ty.errorUnionSet();
2356 if (error_type.errorSetCardinality() == .zero) {
2357 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
2358 return self.lowerConstant(pl_val, ty.errorUnionPayload());
2359 }
2360 const is_pl = val.errorUnionIsPayload();2348 const is_pl = val.errorUnionIsPayload();
2361 const err_val = if (!is_pl) val else Value.initTag(.zero);2349 const err_val = if (!is_pl) val else Value.initTag(.zero);
2362 return self.lowerConstant(err_val, error_type);2350 return self.lowerConstant(err_val, error_type);
...@@ -2925,7 +2913,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W...@@ -2925,7 +2913,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
2925 const err_union_ty = self.air.typeOf(un_op);2913 const err_union_ty = self.air.typeOf(un_op);
2926 const pl_ty = err_union_ty.errorUnionPayload();2914 const pl_ty = err_union_ty.errorUnionPayload();
29272915
2928 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {2916 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
2929 switch (opcode) {2917 switch (opcode) {
2930 .i32_ne => return WValue{ .imm32 = 0 },2918 .i32_ne => return WValue{ .imm32 = 0 },
2931 .i32_eq => return WValue{ .imm32 = 1 },2919 .i32_eq => return WValue{ .imm32 = 1 },
...@@ -2958,10 +2946,6 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool)...@@ -2958,10 +2946,6 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool)
2958 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;2946 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
2959 const payload_ty = err_ty.errorUnionPayload();2947 const payload_ty = err_ty.errorUnionPayload();
29602948
2961 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {
2962 return operand;
2963 }
2964
2965 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };2949 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };
29662950
2967 const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target));2951 const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target));
...@@ -2980,7 +2964,7 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) In...@@ -2980,7 +2964,7 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) In
2980 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;2964 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
2981 const payload_ty = err_ty.errorUnionPayload();2965 const payload_ty = err_ty.errorUnionPayload();
29822966
2983 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {2967 if (err_ty.errorUnionSet().errorSetIsEmpty()) {
2984 return WValue{ .imm32 = 0 };2968 return WValue{ .imm32 = 0 };
2985 }2969 }
29862970
...@@ -2998,10 +2982,6 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2998,10 +2982,6 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2998 const operand = try self.resolveInst(ty_op.operand);2982 const operand = try self.resolveInst(ty_op.operand);
2999 const err_ty = self.air.typeOfIndex(inst);2983 const err_ty = self.air.typeOfIndex(inst);
30002984
3001 if (err_ty.errorUnionSet().errorSetCardinality() == .zero) {
3002 return operand;
3003 }
3004
3005 const pl_ty = self.air.typeOf(ty_op.operand);2985 const pl_ty = self.air.typeOf(ty_op.operand);
3006 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {2986 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
3007 return operand;2987 return operand;
...@@ -4656,29 +4636,27 @@ fn lowerTry(...@@ -4656,29 +4636,27 @@ fn lowerTry(
4656 return self.fail("TODO: lowerTry for pointers", .{});4636 return self.fail("TODO: lowerTry for pointers", .{});
4657 }4637 }
46584638
4659 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
4660 return err_union;
4661 }
4662
4663 const pl_ty = err_union_ty.errorUnionPayload();4639 const pl_ty = err_union_ty.errorUnionPayload();
4664 const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime();4640 const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime();
46654641
4666 // Block we can jump out of when error is not set4642 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
4667 try self.startBlock(.block, wasm.block_empty);4643 // Block we can jump out of when error is not set
46684644 try self.startBlock(.block, wasm.block_empty);
4669 // check if the error tag is set for the error union.4645
4670 try self.emitWValue(err_union);4646 // check if the error tag is set for the error union.
4671 if (pl_has_bits) {4647 try self.emitWValue(err_union);
4672 const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, self.target));4648 if (pl_has_bits) {
4673 try self.addMemArg(.i32_load16_u, .{4649 const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, self.target));
4674 .offset = err_union.offset() + err_offset,4650 try self.addMemArg(.i32_load16_u, .{
4675 .alignment = Type.anyerror.abiAlignment(self.target),4651 .offset = err_union.offset() + err_offset,
4676 });4652 .alignment = Type.anyerror.abiAlignment(self.target),
4653 });
4654 }
4655 try self.addTag(.i32_eqz);
4656 try self.addLabel(.br_if, 0); // jump out of block when error is '0'
4657 try self.genBody(body);
4658 try self.endBlock();
4677 }4659 }
4678 try self.addTag(.i32_eqz);
4679 try self.addLabel(.br_if, 0); // jump out of block when error is '0'
4680 try self.genBody(body);
4681 try self.endBlock();
46824660
4683 // if we reach here it means error was not set, and we want the payload4661 // if we reach here it means error was not set, and we want the payload
4684 if (!pl_has_bits) {4662 if (!pl_has_bits) {
src/arch/x86_64/CodeGen.zig+2-19
...@@ -1806,7 +1806,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1806,7 +1806,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1806 const operand = try self.resolveInst(ty_op.operand);1806 const operand = try self.resolveInst(ty_op.operand);
18071807
1808 const result: MCValue = result: {1808 const result: MCValue = result: {
1809 if (err_ty.errorSetCardinality() == .zero) {1809 if (err_ty.errorSetIsEmpty()) {
1810 break :result MCValue{ .immediate = 0 };1810 break :result MCValue{ .immediate = 0 };
1811 }1811 }
18121812
...@@ -1857,14 +1857,8 @@ fn genUnwrapErrorUnionPayloadMir(...@@ -1857,14 +1857,8 @@ fn genUnwrapErrorUnionPayloadMir(
1857 err_union: MCValue,1857 err_union: MCValue,
1858) !MCValue {1858) !MCValue {
1859 const payload_ty = err_union_ty.errorUnionPayload();1859 const payload_ty = err_union_ty.errorUnionPayload();
1860 const err_ty = err_union_ty.errorUnionSet();
18611860
1862 const result: MCValue = result: {1861 const result: MCValue = result: {
1863 if (err_ty.errorSetCardinality() == .zero) {
1864 // TODO check if we can reuse
1865 break :result err_union;
1866 }
1867
1868 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1862 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1869 break :result MCValue.none;1863 break :result MCValue.none;
1870 }1864 }
...@@ -1991,15 +1985,10 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -1991,15 +1985,10 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
1991 }1985 }
19921986
1993 const error_union_ty = self.air.getRefType(ty_op.ty);1987 const error_union_ty = self.air.getRefType(ty_op.ty);
1994 const error_ty = error_union_ty.errorUnionSet();
1995 const payload_ty = error_union_ty.errorUnionPayload();1988 const payload_ty = error_union_ty.errorUnionPayload();
1996 const operand = try self.resolveInst(ty_op.operand);1989 const operand = try self.resolveInst(ty_op.operand);
19971990
1998 const result: MCValue = result: {1991 const result: MCValue = result: {
1999 if (error_ty.errorSetCardinality() == .zero) {
2000 break :result operand;
2001 }
2002
2003 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1992 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2004 break :result operand;1993 break :result operand;
2005 }1994 }
...@@ -4651,7 +4640,7 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV...@@ -4651,7 +4640,7 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV
4651fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {4640fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
4652 const err_type = ty.errorUnionSet();4641 const err_type = ty.errorUnionSet();
46534642
4654 if (err_type.errorSetCardinality() == .zero) {4643 if (err_type.errorSetIsEmpty()) {
4655 return MCValue{ .immediate = 0 }; // always false4644 return MCValue{ .immediate = 0 }; // always false
4656 }4645 }
46574646
...@@ -6909,12 +6898,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -6909,12 +6898,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
6909 .ErrorUnion => {6898 .ErrorUnion => {
6910 const error_type = typed_value.ty.errorUnionSet();6899 const error_type = typed_value.ty.errorUnionSet();
6911 const payload_type = typed_value.ty.errorUnionPayload();6900 const payload_type = typed_value.ty.errorUnionPayload();
6912
6913 if (error_type.errorSetCardinality() == .zero) {
6914 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
6915 return self.genTypedValue(.{ .ty = payload_type, .val = payload_val });
6916 }
6917
6918 const is_pl = typed_value.val.errorUnionIsPayload();6901 const is_pl = typed_value.val.errorUnionIsPayload();
69196902
6920 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {6903 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
src/codegen.zig-9
...@@ -705,15 +705,6 @@ pub fn generateSymbol(...@@ -705,15 +705,6 @@ pub fn generateSymbol(
705 .ErrorUnion => {705 .ErrorUnion => {
706 const error_ty = typed_value.ty.errorUnionSet();706 const error_ty = typed_value.ty.errorUnionSet();
707 const payload_ty = typed_value.ty.errorUnionPayload();707 const payload_ty = typed_value.ty.errorUnionPayload();
708
709 if (error_ty.errorSetCardinality() == .zero) {
710 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
711 return generateSymbol(bin_file, src_loc, .{
712 .ty = payload_ty,
713 .val = payload_val,
714 }, code, debug_output, reloc_info);
715 }
716
717 const is_payload = typed_value.val.errorUnionIsPayload();708 const is_payload = typed_value.val.errorUnionIsPayload();
718709
719 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {710 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
src/codegen/c.zig+24-52
...@@ -752,12 +752,6 @@ pub const DeclGen = struct {...@@ -752,12 +752,6 @@ pub const DeclGen = struct {
752 const error_type = ty.errorUnionSet();752 const error_type = ty.errorUnionSet();
753 const payload_type = ty.errorUnionPayload();753 const payload_type = ty.errorUnionPayload();
754754
755 if (error_type.errorSetCardinality() == .zero) {
756 // We use the payload directly as the type.
757 const payload_val = val.castTag(.eu_payload).?.data;
758 return dg.renderValue(writer, payload_type, payload_val, location);
759 }
760
761 if (!payload_type.hasRuntimeBits()) {755 if (!payload_type.hasRuntimeBits()) {
762 // We use the error type directly as the type.756 // We use the error type directly as the type.
763 const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;757 const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;
...@@ -1381,13 +1375,8 @@ pub const DeclGen = struct {...@@ -1381,13 +1375,8 @@ pub const DeclGen = struct {
1381 return w.writeAll("uint16_t");1375 return w.writeAll("uint16_t");
1382 },1376 },
1383 .ErrorUnion => {1377 .ErrorUnion => {
1384 const error_ty = t.errorUnionSet();
1385 const payload_ty = t.errorUnionPayload();1378 const payload_ty = t.errorUnionPayload();
13861379
1387 if (error_ty.errorSetCardinality() == .zero) {
1388 return dg.renderType(w, payload_ty);
1389 }
1390
1391 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1380 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1392 return dg.renderType(w, Type.anyerror);1381 return dg.renderType(w, Type.anyerror);
1393 }1382 }
...@@ -2892,41 +2881,36 @@ fn lowerTry(...@@ -2892,41 +2881,36 @@ fn lowerTry(
2892 operand_is_ptr: bool,2881 operand_is_ptr: bool,
2893 result_ty: Type,2882 result_ty: Type,
2894) !CValue {2883) !CValue {
2895 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {2884 const writer = f.object.writer();
2896 // If the error set has no fields, then the payload and the error
2897 // union are the same value.
2898 return err_union;
2899 }
2900
2901 const payload_ty = err_union_ty.errorUnionPayload();2885 const payload_ty = err_union_ty.errorUnionPayload();
2902 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();2886 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
29032887
2904 const writer = f.object.writer();2888 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
29052889 err: {
2906 err: {2890 if (!payload_has_bits) {
2907 if (!payload_has_bits) {2891 if (operand_is_ptr) {
2908 if (operand_is_ptr) {2892 try writer.writeAll("if(*");
2909 try writer.writeAll("if(*");2893 } else {
2910 } else {2894 try writer.writeAll("if(");
2895 }
2896 try f.writeCValue(writer, err_union);
2897 try writer.writeAll(")");
2898 break :err;
2899 }
2900 if (operand_is_ptr or isByRef(err_union_ty)) {
2911 try writer.writeAll("if(");2901 try writer.writeAll("if(");
2902 try f.writeCValue(writer, err_union);
2903 try writer.writeAll("->error)");
2904 break :err;
2912 }2905 }
2913 try f.writeCValue(writer, err_union);
2914 try writer.writeAll(")");
2915 break :err;
2916 }
2917 if (operand_is_ptr or isByRef(err_union_ty)) {
2918 try writer.writeAll("if(");2906 try writer.writeAll("if(");
2919 try f.writeCValue(writer, err_union);2907 try f.writeCValue(writer, err_union);
2920 try writer.writeAll("->error)");2908 try writer.writeAll(".error)");
2921 break :err;
2922 }2909 }
2923 try writer.writeAll("if(");
2924 try f.writeCValue(writer, err_union);
2925 try writer.writeAll(".error)");
2926 }
29272910
2928 try genBody(f, body);2911 try genBody(f, body);
2929 try f.object.indent_writer.insertNewline();2912 try f.object.indent_writer.insertNewline();
2913 }
29302914
2931 if (!payload_has_bits) {2915 if (!payload_has_bits) {
2932 if (!operand_is_ptr) {2916 if (!operand_is_ptr) {
...@@ -3466,7 +3450,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3466,7 +3450,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
34663450
3467 if (operand_ty.zigTypeTag() == .Pointer) {3451 if (operand_ty.zigTypeTag() == .Pointer) {
3468 const err_union_ty = operand_ty.childType();3452 const err_union_ty = operand_ty.childType();
3469 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {3453 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
3470 return CValue{ .bytes = "0" };3454 return CValue{ .bytes = "0" };
3471 }3455 }
3472 if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) {3456 if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) {
...@@ -3478,7 +3462,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3478,7 +3462,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
3478 try writer.writeAll(";\n");3462 try writer.writeAll(";\n");
3479 return local;3463 return local;
3480 }3464 }
3481 if (operand_ty.errorUnionSet().errorSetCardinality() == .zero) {3465 if (operand_ty.errorUnionSet().errorSetIsEmpty()) {
3482 return CValue{ .bytes = "0" };3466 return CValue{ .bytes = "0" };
3483 }3467 }
3484 if (!operand_ty.errorUnionPayload().hasRuntimeBits()) {3468 if (!operand_ty.errorUnionPayload().hasRuntimeBits()) {
...@@ -3507,10 +3491,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c...@@ -3507,10 +3491,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c
3507 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;3491 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
3508 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;3492 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
35093493
3510 if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
3511 return operand;
3512 }
3513
3514 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {3494 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
3515 return CValue.none;3495 return CValue.none;
3516 }3496 }
...@@ -3575,11 +3555,6 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3575,11 +3555,6 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
3575 const error_ty = error_union_ty.errorUnionSet();3555 const error_ty = error_union_ty.errorUnionSet();
3576 const payload_ty = error_union_ty.errorUnionPayload();3556 const payload_ty = error_union_ty.errorUnionPayload();
35773557
3578 if (error_ty.errorSetCardinality() == .zero) {
3579 // TODO: write undefined bytes through the pointer here
3580 return operand;
3581 }
3582
3583 // First, set the non-error value.3558 // First, set the non-error value.
3584 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3559 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3585 try f.writeCValueDeref(writer, operand);3560 try f.writeCValueDeref(writer, operand);
...@@ -3623,9 +3598,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3623,9 +3598,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
3623 const operand = try f.resolveInst(ty_op.operand);3598 const operand = try f.resolveInst(ty_op.operand);
36243599
3625 const inst_ty = f.air.typeOfIndex(inst);3600 const inst_ty = f.air.typeOfIndex(inst);
3626 if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) {
3627 return operand;
3628 }
3629 const local = try f.allocLocal(inst_ty, .Const);3601 const local = try f.allocLocal(inst_ty, .Const);
3630 try writer.writeAll(" = { .error = 0, .payload = ");3602 try writer.writeAll(" = { .error = 0, .payload = ");
3631 try f.writeCValue(writer, operand);3603 try f.writeCValue(writer, operand);
...@@ -3652,7 +3624,7 @@ fn airIsErr(...@@ -3652,7 +3624,7 @@ fn airIsErr(
36523624
3653 try writer.writeAll(" = ");3625 try writer.writeAll(" = ");
36543626
3655 if (error_ty.errorSetCardinality() == .zero) {3627 if (error_ty.errorSetIsEmpty()) {
3656 try writer.print("0 {s} 0;\n", .{op_str});3628 try writer.print("0 {s} 0;\n", .{op_str});
3657 } else {3629 } else {
3658 if (is_ptr) {3630 if (is_ptr) {
src/codegen/llvm.zig+26-72
...@@ -1571,22 +1571,6 @@ pub const Object = struct {...@@ -1571,22 +1571,6 @@ pub const Object = struct {
1571 },1571 },
1572 .ErrorUnion => {1572 .ErrorUnion => {
1573 const payload_ty = ty.errorUnionPayload();1573 const payload_ty = ty.errorUnionPayload();
1574 switch (ty.errorUnionSet().errorSetCardinality()) {
1575 .zero => {
1576 const payload_di_ty = try o.lowerDebugType(payload_ty, .full);
1577 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1578 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(payload_di_ty), .{ .mod = o.module });
1579 return payload_di_ty;
1580 },
1581 .one => {
1582 if (payload_ty.isNoReturn()) {
1583 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
1584 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
1585 return di_type;
1586 }
1587 },
1588 .many => {},
1589 }
1590 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1574 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1591 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);1575 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
1592 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1576 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
...@@ -2554,15 +2538,6 @@ pub const DeclGen = struct {...@@ -2554,15 +2538,6 @@ pub const DeclGen = struct {
2554 },2538 },
2555 .ErrorUnion => {2539 .ErrorUnion => {
2556 const payload_ty = t.errorUnionPayload();2540 const payload_ty = t.errorUnionPayload();
2557 switch (t.errorUnionSet().errorSetCardinality()) {
2558 .zero => return dg.lowerType(payload_ty),
2559 .one => {
2560 if (payload_ty.isNoReturn()) {
2561 return dg.context.voidType();
2562 }
2563 },
2564 .many => {},
2565 }
2566 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {2541 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2567 return try dg.lowerType(Type.anyerror);2542 return try dg.lowerType(Type.anyerror);
2568 }2543 }
...@@ -3222,10 +3197,6 @@ pub const DeclGen = struct {...@@ -3222,10 +3197,6 @@ pub const DeclGen = struct {
3222 },3197 },
3223 .ErrorUnion => {3198 .ErrorUnion => {
3224 const payload_type = tv.ty.errorUnionPayload();3199 const payload_type = tv.ty.errorUnionPayload();
3225 if (tv.ty.errorUnionSet().errorSetCardinality() == .zero) {
3226 const payload_val = tv.val.castTag(.eu_payload).?.data;
3227 return dg.lowerValue(.{ .ty = payload_type, .val = payload_val });
3228 }
3229 const is_pl = tv.val.errorUnionIsPayload();3200 const is_pl = tv.val.errorUnionIsPayload();
32303201
3231 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {3202 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
...@@ -4795,40 +4766,37 @@ pub const FuncGen = struct {...@@ -4795,40 +4766,37 @@ pub const FuncGen = struct {
4795 }4766 }
47964767
4797 fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value {4768 fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value {
4798 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
4799 // If the error set has no fields, then the payload and the error
4800 // union are the same value.
4801 return err_union;
4802 }
4803
4804 const payload_ty = err_union_ty.errorUnionPayload();4769 const payload_ty = err_union_ty.errorUnionPayload();
4805 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();4770 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
4806 const target = fg.dg.module.getTarget();4771 const target = fg.dg.module.getTarget();
4807 const is_err = err: {4772
4808 const err_set_ty = try fg.dg.lowerType(Type.anyerror);4773 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
4809 const zero = err_set_ty.constNull();4774 const is_err = err: {
4810 if (!payload_has_bits) {4775 const err_set_ty = try fg.dg.lowerType(Type.anyerror);
4811 const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union;4776 const zero = err_set_ty.constNull();
4812 break :err fg.builder.buildICmp(.NE, loaded, zero, "");4777 if (!payload_has_bits) {
4813 }4778 const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union;
4814 const err_field_index = errUnionErrorOffset(payload_ty, target);4779 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
4815 if (operand_is_ptr or isByRef(err_union_ty)) {4780 }
4816 const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, "");4781 const err_field_index = errUnionErrorOffset(payload_ty, target);
4817 const loaded = fg.builder.buildLoad(err_field_ptr, "");4782 if (operand_is_ptr or isByRef(err_union_ty)) {
4783 const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, "");
4784 const loaded = fg.builder.buildLoad(err_field_ptr, "");
4785 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
4786 }
4787 const loaded = fg.builder.buildExtractValue(err_union, err_field_index, "");
4818 break :err fg.builder.buildICmp(.NE, loaded, zero, "");4788 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
4819 }4789 };
4820 const loaded = fg.builder.buildExtractValue(err_union, err_field_index, "");
4821 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
4822 };
48234790
4824 const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet");4791 const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet");
4825 const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont");4792 const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont");
4826 _ = fg.builder.buildCondBr(is_err, return_block, continue_block);4793 _ = fg.builder.buildCondBr(is_err, return_block, continue_block);
48274794
4828 fg.builder.positionBuilderAtEnd(return_block);4795 fg.builder.positionBuilderAtEnd(return_block);
4829 try fg.genBody(body);4796 try fg.genBody(body);
48304797
4831 fg.builder.positionBuilderAtEnd(continue_block);4798 fg.builder.positionBuilderAtEnd(continue_block);
4799 }
4832 if (!payload_has_bits) {4800 if (!payload_has_bits) {
4833 if (!operand_is_ptr) return null;4801 if (!operand_is_ptr) return null;
48344802
...@@ -5665,7 +5633,7 @@ pub const FuncGen = struct {...@@ -5665,7 +5633,7 @@ pub const FuncGen = struct {
5665 const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror));5633 const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror));
5666 const zero = err_set_ty.constNull();5634 const zero = err_set_ty.constNull();
56675635
5668 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {5636 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
5669 const llvm_i1 = self.context.intType(1);5637 const llvm_i1 = self.context.intType(1);
5670 switch (op) {5638 switch (op) {
5671 .EQ => return llvm_i1.constInt(1, .False), // 0 == 05639 .EQ => return llvm_i1.constInt(1, .False), // 0 == 0
...@@ -5788,13 +5756,6 @@ pub const FuncGen = struct {...@@ -5788,13 +5756,6 @@ pub const FuncGen = struct {
57885756
5789 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5757 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5790 const operand = try self.resolveInst(ty_op.operand);5758 const operand = try self.resolveInst(ty_op.operand);
5791 const operand_ty = self.air.typeOf(ty_op.operand);
5792 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
5793 if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
5794 // If the error set has no fields, then the payload and the error
5795 // union are the same value.
5796 return operand;
5797 }
5798 const result_ty = self.air.typeOfIndex(inst);5759 const result_ty = self.air.typeOfIndex(inst);
5799 const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;5760 const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;
5800 const target = self.dg.module.getTarget();5761 const target = self.dg.module.getTarget();
...@@ -5825,7 +5786,7 @@ pub const FuncGen = struct {...@@ -5825,7 +5786,7 @@ pub const FuncGen = struct {
5825 const operand = try self.resolveInst(ty_op.operand);5786 const operand = try self.resolveInst(ty_op.operand);
5826 const operand_ty = self.air.typeOf(ty_op.operand);5787 const operand_ty = self.air.typeOf(ty_op.operand);
5827 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;5788 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
5828 if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {5789 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
5829 const err_llvm_ty = try self.dg.lowerType(Type.anyerror);5790 const err_llvm_ty = try self.dg.lowerType(Type.anyerror);
5830 if (operand_is_ptr) {5791 if (operand_is_ptr) {
5831 return self.builder.buildBitCast(operand, err_llvm_ty.pointerType(0), "");5792 return self.builder.buildBitCast(operand, err_llvm_ty.pointerType(0), "");
...@@ -5856,10 +5817,6 @@ pub const FuncGen = struct {...@@ -5856,10 +5817,6 @@ pub const FuncGen = struct {
5856 const operand = try self.resolveInst(ty_op.operand);5817 const operand = try self.resolveInst(ty_op.operand);
5857 const error_union_ty = self.air.typeOf(ty_op.operand).childType();5818 const error_union_ty = self.air.typeOf(ty_op.operand).childType();
58585819
5859 if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
5860 // TODO: write undefined bytes through the pointer here
5861 return operand;
5862 }
5863 const payload_ty = error_union_ty.errorUnionPayload();5820 const payload_ty = error_union_ty.errorUnionPayload();
5864 const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero });5821 const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero });
5865 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {5822 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
...@@ -5938,9 +5895,6 @@ pub const FuncGen = struct {...@@ -5938,9 +5895,6 @@ pub const FuncGen = struct {
5938 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5895 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5939 const inst_ty = self.air.typeOfIndex(inst);5896 const inst_ty = self.air.typeOfIndex(inst);
5940 const operand = try self.resolveInst(ty_op.operand);5897 const operand = try self.resolveInst(ty_op.operand);
5941 if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) {
5942 return operand;
5943 }
5944 const payload_ty = self.air.typeOf(ty_op.operand);5898 const payload_ty = self.air.typeOf(ty_op.operand);
5945 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {5899 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
5946 return operand;5900 return operand;
src/type.zig+29-163
...@@ -2366,6 +2366,10 @@ pub const Type = extern union {...@@ -2366,6 +2366,10 @@ pub const Type = extern union {
2366 .anyopaque,2366 .anyopaque,
2367 .@"opaque",2367 .@"opaque",
2368 .type_info,2368 .type_info,
2369 .error_set_single,
2370 .error_union,
2371 .error_set,
2372 .error_set_merged,
2369 => return true,2373 => return true,
23702374
2371 // These are false because they are comptime-only types.2375 // These are false because they are comptime-only types.
...@@ -2389,20 +2393,8 @@ pub const Type = extern union {...@@ -2389,20 +2393,8 @@ pub const Type = extern union {
2389 .fn_void_no_args,2393 .fn_void_no_args,
2390 .fn_naked_noreturn_no_args,2394 .fn_naked_noreturn_no_args,
2391 .fn_ccc_void_no_args,2395 .fn_ccc_void_no_args,
2392 .error_set_single,
2393 => return false,2396 => return false,
23942397
2395 .error_set => {
2396 const err_set_obj = ty.castTag(.error_set).?.data;
2397 const names = err_set_obj.names.keys();
2398 return names.len > 1;
2399 },
2400 .error_set_merged => {
2401 const name_map = ty.castTag(.error_set_merged).?.data;
2402 const names = name_map.keys();
2403 return names.len > 1;
2404 },
2405
2406 // These types have more than one possible value, so the result is the same as2398 // These types have more than one possible value, so the result is the same as
2407 // asking whether they are comptime-only types.2399 // asking whether they are comptime-only types.
2408 .anyframe_T,2400 .anyframe_T,
...@@ -2443,25 +2435,6 @@ pub const Type = extern union {...@@ -2443,25 +2435,6 @@ pub const Type = extern union {
2443 }2435 }
2444 },2436 },
24452437
2446 .error_union => {
2447 // This code needs to be kept in sync with the equivalent switch prong
2448 // in abiSizeAdvanced.
2449 const data = ty.castTag(.error_union).?.data;
2450 switch (data.error_set.errorSetCardinality()) {
2451 .zero => return hasRuntimeBitsAdvanced(data.payload, ignore_comptime_only, sema_kit),
2452 .one => return !data.payload.isNoReturn(),
2453 .many => {
2454 if (ignore_comptime_only) {
2455 return true;
2456 } else if (sema_kit) |sk| {
2457 return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
2458 } else {
2459 return !comptimeOnly(ty);
2460 }
2461 },
2462 }
2463 },
2464
2465 .@"struct" => {2438 .@"struct" => {
2466 const struct_obj = ty.castTag(.@"struct").?.data;2439 const struct_obj = ty.castTag(.@"struct").?.data;
2467 if (struct_obj.status == .field_types_wip) {2440 if (struct_obj.status == .field_types_wip) {
...@@ -2926,27 +2899,11 @@ pub const Type = extern union {...@@ -2926,27 +2899,11 @@ pub const Type = extern union {
2926 .anyerror_void_error_union,2899 .anyerror_void_error_union,
2927 .anyerror,2900 .anyerror,
2928 .error_set_inferred,2901 .error_set_inferred,
2902 .error_set_single,
2903 .error_set,
2904 .error_set_merged,
2929 => return AbiAlignmentAdvanced{ .scalar = 2 },2905 => return AbiAlignmentAdvanced{ .scalar = 2 },
29302906
2931 .error_set => {
2932 const err_set_obj = ty.castTag(.error_set).?.data;
2933 const names = err_set_obj.names.keys();
2934 if (names.len <= 1) {
2935 return AbiAlignmentAdvanced{ .scalar = 0 };
2936 } else {
2937 return AbiAlignmentAdvanced{ .scalar = 2 };
2938 }
2939 },
2940 .error_set_merged => {
2941 const name_map = ty.castTag(.error_set_merged).?.data;
2942 const names = name_map.keys();
2943 if (names.len <= 1) {
2944 return AbiAlignmentAdvanced{ .scalar = 0 };
2945 } else {
2946 return AbiAlignmentAdvanced{ .scalar = 2 };
2947 }
2948 },
2949
2950 .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat),2907 .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat),
29512908
2952 // TODO audit this - is there any more complicated logic to determine2909 // TODO audit this - is there any more complicated logic to determine
...@@ -2971,12 +2928,7 @@ pub const Type = extern union {...@@ -2971,12 +2928,7 @@ pub const Type = extern union {
29712928
2972 switch (child_type.zigTypeTag()) {2929 switch (child_type.zigTypeTag()) {
2973 .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },2930 .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
2974 .ErrorSet => switch (child_type.errorSetCardinality()) {2931 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, target, strat),
2975 // `?error{}` is comptime-known to be null.
2976 .zero => return AbiAlignmentAdvanced{ .scalar = 0 },
2977 .one => return AbiAlignmentAdvanced{ .scalar = 1 },
2978 .many => return abiAlignmentAdvanced(Type.anyerror, target, strat),
2979 },
2980 .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },2932 .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },
2981 else => {},2933 else => {},
2982 }2934 }
...@@ -2999,15 +2951,6 @@ pub const Type = extern union {...@@ -2999,15 +2951,6 @@ pub const Type = extern union {
2999 // This code needs to be kept in sync with the equivalent switch prong2951 // This code needs to be kept in sync with the equivalent switch prong
3000 // in abiSizeAdvanced.2952 // in abiSizeAdvanced.
3001 const data = ty.castTag(.error_union).?.data;2953 const data = ty.castTag(.error_union).?.data;
3002 switch (data.error_set.errorSetCardinality()) {
3003 .zero => return abiAlignmentAdvanced(data.payload, target, strat),
3004 .one => {
3005 if (data.payload.isNoReturn()) {
3006 return AbiAlignmentAdvanced{ .scalar = 0 };
3007 }
3008 },
3009 .many => {},
3010 }
3011 const code_align = abiAlignment(Type.anyerror, target);2954 const code_align = abiAlignment(Type.anyerror, target);
3012 switch (strat) {2955 switch (strat) {
3013 .eager, .sema_kit => {2956 .eager, .sema_kit => {
...@@ -3118,7 +3061,6 @@ pub const Type = extern union {...@@ -3118,7 +3061,6 @@ pub const Type = extern union {
3118 .@"undefined",3061 .@"undefined",
3119 .enum_literal,3062 .enum_literal,
3120 .type_info,3063 .type_info,
3121 .error_set_single,
3122 => return AbiAlignmentAdvanced{ .scalar = 0 },3064 => return AbiAlignmentAdvanced{ .scalar = 0 },
31233065
3124 .noreturn,3066 .noreturn,
...@@ -3237,7 +3179,6 @@ pub const Type = extern union {...@@ -3237,7 +3179,6 @@ pub const Type = extern union {
3237 .empty_struct_literal,3179 .empty_struct_literal,
3238 .empty_struct,3180 .empty_struct,
3239 .void,3181 .void,
3240 .error_set_single,
3241 => return AbiSizeAdvanced{ .scalar = 0 },3182 => return AbiSizeAdvanced{ .scalar = 0 },
32423183
3243 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {3184 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
...@@ -3396,27 +3337,11 @@ pub const Type = extern union {...@@ -3396,27 +3337,11 @@ pub const Type = extern union {
3396 .anyerror_void_error_union,3337 .anyerror_void_error_union,
3397 .anyerror,3338 .anyerror,
3398 .error_set_inferred,3339 .error_set_inferred,
3340 .error_set,
3341 .error_set_merged,
3342 .error_set_single,
3399 => return AbiSizeAdvanced{ .scalar = 2 },3343 => return AbiSizeAdvanced{ .scalar = 2 },
34003344
3401 .error_set => {
3402 const err_set_obj = ty.castTag(.error_set).?.data;
3403 const names = err_set_obj.names.keys();
3404 if (names.len <= 1) {
3405 return AbiSizeAdvanced{ .scalar = 0 };
3406 } else {
3407 return AbiSizeAdvanced{ .scalar = 2 };
3408 }
3409 },
3410 .error_set_merged => {
3411 const name_map = ty.castTag(.error_set_merged).?.data;
3412 const names = name_map.keys();
3413 if (names.len <= 1) {
3414 return AbiSizeAdvanced{ .scalar = 0 };
3415 } else {
3416 return AbiSizeAdvanced{ .scalar = 2 };
3417 }
3418 },
3419
3420 .i16, .u16 => return AbiSizeAdvanced{ .scalar = intAbiSize(16, target) },3345 .i16, .u16 => return AbiSizeAdvanced{ .scalar = intAbiSize(16, target) },
3421 .u29 => return AbiSizeAdvanced{ .scalar = intAbiSize(29, target) },3346 .u29 => return AbiSizeAdvanced{ .scalar = intAbiSize(29, target) },
3422 .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) },3347 .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) },
...@@ -3467,24 +3392,6 @@ pub const Type = extern union {...@@ -3467,24 +3392,6 @@ pub const Type = extern union {
3467 // This code needs to be kept in sync with the equivalent switch prong3392 // This code needs to be kept in sync with the equivalent switch prong
3468 // in abiAlignmentAdvanced.3393 // in abiAlignmentAdvanced.
3469 const data = ty.castTag(.error_union).?.data;3394 const data = ty.castTag(.error_union).?.data;
3470 // Here we need to care whether or not the error set is *empty* or whether
3471 // it only has *one possible value*. In the former case, it means there
3472 // cannot possibly be an error, meaning the ABI size is equivalent to the
3473 // payload ABI size. In the latter case, we need to account for the "tag"
3474 // because even if both the payload type and the error set type of an
3475 // error union have no runtime bits, an error union still has
3476 // 1 bit of data which is whether or not the value is an error.
3477 // Zig still uses the error code encoding at runtime, even when only 1 bit
3478 // would suffice. This prevents coercions from needing to branch.
3479 switch (data.error_set.errorSetCardinality()) {
3480 .zero => return abiSizeAdvanced(data.payload, target, strat),
3481 .one => {
3482 if (data.payload.isNoReturn()) {
3483 return AbiSizeAdvanced{ .scalar = 0 };
3484 }
3485 },
3486 .many => {},
3487 }
3488 const code_size = abiSize(Type.anyerror, target);3395 const code_size = abiSize(Type.anyerror, target);
3489 if (!data.payload.hasRuntimeBits()) {3396 if (!data.payload.hasRuntimeBits()) {
3490 // Same as anyerror.3397 // Same as anyerror.
...@@ -3727,11 +3634,7 @@ pub const Type = extern union {...@@ -3727,11 +3634,7 @@ pub const Type = extern union {
37273634
3728 .error_union => {3635 .error_union => {
3729 const payload = ty.castTag(.error_union).?.data;3636 const payload = ty.castTag(.error_union).?.data;
3730 if (!payload.error_set.hasRuntimeBits() and !payload.payload.hasRuntimeBits()) {3637 if (!payload.payload.hasRuntimeBits()) {
3731 return 0;
3732 } else if (!payload.error_set.hasRuntimeBits()) {
3733 return payload.payload.bitSizeAdvanced(target, sema_kit);
3734 } else if (!payload.payload.hasRuntimeBits()) {
3735 return payload.error_set.bitSizeAdvanced(target, sema_kit);3638 return payload.error_set.bitSizeAdvanced(target, sema_kit);
3736 }3639 }
3737 @panic("TODO bitSize error union");3640 @panic("TODO bitSize error union");
...@@ -4351,30 +4254,25 @@ pub const Type = extern union {...@@ -4351,30 +4254,25 @@ pub const Type = extern union {
4351 };4254 };
4352 }4255 }
43534256
4354 const ErrorSetCardinality = enum { zero, one, many };4257 /// Returns false for unresolved inferred error sets.
43554258 pub fn errorSetIsEmpty(ty: Type) bool {
4356 pub fn errorSetCardinality(ty: Type) ErrorSetCardinality {
4357 switch (ty.tag()) {4259 switch (ty.tag()) {
4358 .anyerror => return .many,4260 .anyerror => return false,
4359 .error_set_inferred => return .many,4261 .error_set_inferred => {
4360 .error_set_single => return .one,4262 const inferred_error_set = ty.castTag(.error_set_inferred).?.data;
4263 // Can't know for sure.
4264 if (!inferred_error_set.is_resolved) return false;
4265 if (inferred_error_set.is_anyerror) return false;
4266 return inferred_error_set.errors.count() == 0;
4267 },
4268 .error_set_single => return false,
4361 .error_set => {4269 .error_set => {
4362 const err_set_obj = ty.castTag(.error_set).?.data;4270 const err_set_obj = ty.castTag(.error_set).?.data;
4363 const names = err_set_obj.names.keys();4271 return err_set_obj.names.count() == 0;
4364 switch (names.len) {
4365 0 => return .zero,
4366 1 => return .one,
4367 else => return .many,
4368 }
4369 },4272 },
4370 .error_set_merged => {4273 .error_set_merged => {
4371 const name_map = ty.castTag(.error_set_merged).?.data;4274 const name_map = ty.castTag(.error_set_merged).?.data;
4372 const names = name_map.keys();4275 return name_map.count() == 0;
4373 switch (names.len) {
4374 0 => return .zero,
4375 1 => return .one,
4376 else => return .many,
4377 }
4378 },4276 },
4379 else => unreachable,4277 else => unreachable,
4380 }4278 }
...@@ -4883,6 +4781,10 @@ pub const Type = extern union {...@@ -4883,6 +4781,10 @@ pub const Type = extern union {
4883 .bool,4781 .bool,
4884 .type,4782 .type,
4885 .anyerror,4783 .anyerror,
4784 .error_union,
4785 .error_set_single,
4786 .error_set,
4787 .error_set_merged,
4886 .fn_noreturn_no_args,4788 .fn_noreturn_no_args,
4887 .fn_void_no_args,4789 .fn_void_no_args,
4888 .fn_naked_noreturn_no_args,4790 .fn_naked_noreturn_no_args,
...@@ -4939,42 +4841,6 @@ pub const Type = extern union {...@@ -4939,42 +4841,6 @@ pub const Type = extern union {
4939 }4841 }
4940 },4842 },
49414843
4942 .error_union => {
4943 const error_ty = ty.errorUnionSet();
4944 switch (error_ty.errorSetCardinality()) {
4945 .zero => {
4946 const payload_ty = ty.errorUnionPayload();
4947 if (onePossibleValue(payload_ty)) |payload_val| {
4948 _ = payload_val;
4949 return Value.initTag(.the_only_possible_value);
4950 } else {
4951 return null;
4952 }
4953 },
4954 .one => {
4955 if (ty.errorUnionPayload().isNoReturn()) {
4956 const error_val = onePossibleValue(error_ty).?;
4957 return error_val;
4958 } else {
4959 return null;
4960 }
4961 },
4962 .many => return null,
4963 }
4964 },
4965
4966 .error_set_single => return Value.initTag(.the_only_possible_value),
4967 .error_set => {
4968 const err_set_obj = ty.castTag(.error_set).?.data;
4969 if (err_set_obj.names.count() > 1) return null;
4970 return Value.initTag(.the_only_possible_value);
4971 },
4972 .error_set_merged => {
4973 const name_map = ty.castTag(.error_set_merged).?.data;
4974 if (name_map.count() > 1) return null;
4975 return Value.initTag(.the_only_possible_value);
4976 },
4977
4978 .@"struct" => {4844 .@"struct" => {
4979 const s = ty.castTag(.@"struct").?.data;4845 const s = ty.castTag(.@"struct").?.data;
4980 assert(s.haveFieldTypes());4846 assert(s.haveFieldTypes());
test/behavior/error.zig-59
...@@ -453,65 +453,6 @@ test "optional error set is the same size as error set" {...@@ -453,65 +453,6 @@ test "optional error set is the same size as error set" {
453 comptime try expect(S.returnsOptErrSet() == null);453 comptime try expect(S.returnsOptErrSet() == null);
454}454}
455455
456test "optional error set with only one error is the same size as bool" {
457 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
458 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
459 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
460
461 const E = error{only};
462 comptime try expect(@sizeOf(?E) == @sizeOf(bool));
463 comptime try expect(@alignOf(?E) == @alignOf(bool));
464 const S = struct {
465 fn gimmeNull() ?E {
466 return null;
467 }
468 fn gimmeErr() ?E {
469 return error.only;
470 }
471 };
472 try expect(S.gimmeNull() == null);
473 try expect(error.only == S.gimmeErr().?);
474 comptime try expect(S.gimmeNull() == null);
475 comptime try expect(error.only == S.gimmeErr().?);
476}
477
478test "optional empty error set" {
479 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
480
481 comptime try expect(@sizeOf(error{}!void) == @sizeOf(void));
482 comptime try expect(@alignOf(error{}!void) == @alignOf(void));
483
484 var x: ?error{} = undefined;
485 if (x != null) {
486 @compileError("test failed");
487 }
488}
489
490test "empty error set plus zero-bit payload" {
491 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
492 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
494
495 comptime try expect(@sizeOf(error{}!void) == @sizeOf(void));
496 comptime try expect(@alignOf(error{}!void) == @alignOf(void));
497
498 var x: error{}!void = undefined;
499 if (x) |payload| {
500 if (payload != {}) {
501 @compileError("test failed");
502 }
503 } else |_| {
504 @compileError("test failed");
505 }
506 const S = struct {
507 fn empty() error{}!void {}
508 fn inferred() !void {
509 return empty();
510 }
511 };
512 try S.inferred();
513}
514
515test "nested catch" {456test "nested catch" {
516 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO458 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO