| author | |
| committer | |
| log | 0333ff4476d0132a2397122dcab964de7fc0f2d3 |
| tree | 8032dc588ab76313580feec71e07077ab1209960 |
| parent | 488e1e5f51905485f9db37038e74bdea31ebd16e |
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 | } |
| 180 | 180 | ||
| 181 | test "very long sparse chunk" { | 181 | test "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.maxInsertIndex | 376 | // Update the hash for best_speed only if d.index < d.maxInsertIndex |
| 378 | // See https://golang.org/issue/2508 | 377 | // See https://golang.org/issue/2508 |
| 379 | test "Go non-regression test for 2508" { | 378 | test "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 | } |
| 6184 | 6184 | ||
| 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( |
| 6560 | 6571 | ||
| 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() and | 6573 | 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( |
| 6646 | 6657 | ||
| 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() and | 6659 | 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 | }, |
| 24289 | 24304 | ||
| 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 { |
| 2277 | fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { | 2277 | fn 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 { |
| 2311 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { | 2311 | fn 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(); |
| 3592 | 3592 | ||
| 3593 | if (error_type.errorSetCardinality() == .zero) { | 3593 | if (error_type.errorSetIsEmpty()) { |
| 3594 | return MCValue{ .immediate = 0 }; // always false | 3594 | return MCValue{ .immediate = 0 }; // always false |
| 3595 | } | 3595 | } |
| 3596 | 3596 | ||
| ... | @@ -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(); |
| 4689 | 4689 | ||
| 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(); |
| 4696 | 4691 | ||
| 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 { |
| 1773 | fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { | 1773 | fn 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 { |
| 1810 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { | 1810 | fn 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); |
| 3924 | 3924 | ||
| 3925 | if (error_type.errorSetCardinality() == .zero) { | 3925 | if (error_type.errorSetIsEmpty()) { |
| 3926 | return MCValue{ .immediate = 0 }; // always false | 3926 | return MCValue{ .immediate = 0 }; // always false |
| 3927 | } | 3927 | } |
| 3928 | 3928 | ||
| ... | @@ -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(); |
| 5378 | 5372 | ||
| 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 { |
| 1816 | fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void { | 1812 | fn 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(); |
| 2927 | 2915 | ||
| 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(); |
| 2960 | 2948 | ||
| 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 = {} }; |
| 2966 | 2950 | ||
| 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(); |
| 2982 | 2966 | ||
| 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 | } |
| 2986 | 2970 | ||
| ... | @@ -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); |
| 3000 | 2984 | ||
| 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 | } |
| 4658 | 4638 | ||
| 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(); |
| 4665 | 4641 | ||
| 4666 | // Block we can jump out of when error is not set | 4642 | 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 |
| 4668 | 4644 | 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(); | ||
| 4682 | 4660 | ||
| 4683 | // if we reach here it means error was not set, and we want the payload | 4661 | // 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); |
| 1807 | 1807 | ||
| 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 | } |
| 1812 | 1812 | ||
| ... | @@ -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(); | ||
| 1861 | 1860 | ||
| 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 | } |
| 1992 | 1986 | ||
| 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); |
| 1997 | 1990 | ||
| 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 |
| 4651 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { | 4640 | fn 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(); |
| 4653 | 4642 | ||
| 4654 | if (err_type.errorSetCardinality() == .zero) { | 4643 | if (err_type.errorSetIsEmpty()) { |
| 4655 | return MCValue{ .immediate = 0 }; // always false | 4644 | return MCValue{ .immediate = 0 }; // always false |
| 4656 | } | 4645 | } |
| 4657 | 4646 | ||
| ... | @@ -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(); |
| 6919 | 6902 | ||
| 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(); |
| 718 | 709 | ||
| 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(); |
| 754 | 754 | ||
| 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(); |
| 1386 | 1379 | ||
| 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(); |
| 2903 | 2887 | ||
| 2904 | const writer = f.object.writer(); | 2888 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { |
| 2905 | 2889 | 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 | } | ||
| 2927 | 2910 | ||
| 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 | } | ||
| 2930 | 2914 | ||
| 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 { |
| 3466 | 3450 | ||
| 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; |
| 3509 | 3493 | ||
| 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(); |
| 3577 | 3557 | ||
| 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); |
| 3624 | 3599 | ||
| 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( |
| 3652 | 3624 | ||
| 3653 | try writer.writeAll(" = "); | 3625 | try writer.writeAll(" = "); |
| 3654 | 3626 | ||
| 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(); |
| 3230 | 3201 | ||
| 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 | } |
| 4796 | 4767 | ||
| 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 | }; | ||
| 4823 | 4790 | ||
| 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); |
| 4827 | 4794 | ||
| 4828 | fg.builder.positionBuilderAtEnd(return_block); | 4795 | fg.builder.positionBuilderAtEnd(return_block); |
| 4829 | try fg.genBody(body); | 4796 | try fg.genBody(body); |
| 4830 | 4797 | ||
| 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; |
| 4834 | 4802 | ||
| ... | @@ -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(); |
| 5667 | 5635 | ||
| 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 == 0 | 5639 | .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 { |
| 5788 | 5756 | ||
| 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(); |
| 5858 | 5819 | ||
| 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, |
| 2370 | 2374 | ||
| 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, |
| 2394 | 2397 | ||
| 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 as | 2398 | // 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 | }, |
| 2445 | 2437 | ||
| 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 }, |
| 2930 | 2906 | ||
| 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), |
| 2951 | 2908 | ||
| 2952 | // TODO audit this - is there any more complicated logic to determine | 2909 | // 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 { |
| 2971 | 2928 | ||
| 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 prong | 2951 | // 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 }, |
| 3123 | 3065 | ||
| 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 }, |
| 3242 | 3183 | ||
| 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 }, |
| 3400 | 3344 | ||
| 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 prong | 3392 | // 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 { |
| 3727 | 3634 | ||
| 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 | } |
| 4353 | 4256 | ||
| 4354 | const ErrorSetCardinality = enum { zero, one, many }; | 4257 | /// Returns false for unresolved inferred error sets. |
| 4355 | 4258 | 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 | }, |
| 4941 | 4843 | ||
| 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 | } |
| 455 | 455 | ||
| 456 | test "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 | |||
| 478 | test "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 | |||
| 490 | test "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 | |||
| 515 | test "nested catch" { | 456 | test "nested catch" { |
| 516 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 457 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 517 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 458 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |