| author | |
| committer | |
| log | be1b23120648dff5e23d67b089c10b479564bffd |
| tree | 79e455747856a29c096ee4f5e5ef61e7186b57c2 |
| parent | 9584feae5f27a8b987975d8fe8242e2169098a75 |
3 files changed, 84 insertions(+), 30 deletions(-)
src/InternPool.zig+41-4| ... | ... | @@ -1517,6 +1517,8 @@ pub const Tag = enum(u8) { |
| 1517 | 1517 | /// 0. name: NullTerminatedString for each names_len |
| 1518 | 1518 | pub const ErrorSet = struct { |
| 1519 | 1519 | names_len: u32, |
| 1520 | /// Maps error names to declaration index. | |
| 1521 | names_map: MapIndex, | |
| 1520 | 1522 | }; |
| 1521 | 1523 | |
| 1522 | 1524 | /// Trailing: |
| ... | ... | @@ -2024,6 +2026,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 2024 | 2026 | const names = ip.extra.items[error_set.end..][0..names_len]; |
| 2025 | 2027 | return .{ .error_set_type = .{ |
| 2026 | 2028 | .names = @ptrCast([]const NullTerminatedString, names), |
| 2029 | .names_map = error_set.data.names_map.toOptional(), | |
| 2027 | 2030 | } }; |
| 2028 | 2031 | }, |
| 2029 | 2032 | .type_inferred_error_set => .{ |
| ... | ... | @@ -2518,6 +2521,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 2518 | 2521 | .tag = .type_error_set, |
| 2519 | 2522 | .data = ip.addExtraAssumeCapacity(ErrorSet{ |
| 2520 | 2523 | .names_len = names_len, |
| 2524 | .names_map = names_map, | |
| 2521 | 2525 | }), |
| 2522 | 2526 | }); |
| 2523 | 2527 | ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names)); |
| ... | ... | @@ -3605,15 +3609,34 @@ pub fn sliceLen(ip: InternPool, i: Index) Index { |
| 3605 | 3609 | /// * int <=> int |
| 3606 | 3610 | /// * int <=> enum |
| 3607 | 3611 | /// * ptr <=> ptr |
| 3612 | /// * null_value => opt | |
| 3613 | /// * payload => opt | |
| 3608 | 3614 | pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { |
| 3609 | if (ip.typeOf(val) == new_ty) return val; | |
| 3615 | const old_ty = ip.typeOf(val); | |
| 3616 | if (old_ty == new_ty) return val; | |
| 3610 | 3617 | switch (ip.indexToKey(val)) { |
| 3611 | 3618 | .int => |int| switch (ip.indexToKey(new_ty)) { |
| 3619 | .simple_type => |simple_type| switch (simple_type) { | |
| 3620 | .usize, | |
| 3621 | .isize, | |
| 3622 | .c_char, | |
| 3623 | .c_short, | |
| 3624 | .c_ushort, | |
| 3625 | .c_int, | |
| 3626 | .c_uint, | |
| 3627 | .c_long, | |
| 3628 | .c_ulong, | |
| 3629 | .c_longlong, | |
| 3630 | .c_ulonglong, | |
| 3631 | => return getCoercedInts(ip, gpa, int, new_ty), | |
| 3632 | else => {}, | |
| 3633 | }, | |
| 3634 | .int_type => return getCoercedInts(ip, gpa, int, new_ty), | |
| 3612 | 3635 | .enum_type => return ip.get(gpa, .{ .enum_tag = .{ |
| 3613 | 3636 | .ty = new_ty, |
| 3614 | 3637 | .int = val, |
| 3615 | 3638 | } }), |
| 3616 | else => return getCoercedInts(ip, gpa, int, new_ty), | |
| 3639 | else => {}, | |
| 3617 | 3640 | }, |
| 3618 | 3641 | .enum_tag => |enum_tag| { |
| 3619 | 3642 | // Assume new_ty is an integer type. |
| ... | ... | @@ -3624,10 +3647,24 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al |
| 3624 | 3647 | .ty = new_ty, |
| 3625 | 3648 | .addr = ptr.addr, |
| 3626 | 3649 | } }), |
| 3627 | else => unreachable, | |
| 3650 | else => {}, | |
| 3628 | 3651 | }, |
| 3629 | else => unreachable, | |
| 3652 | else => {}, | |
| 3653 | } | |
| 3654 | switch (ip.indexToKey(new_ty)) { | |
| 3655 | .opt_type => |child_ty| switch (val) { | |
| 3656 | .null_value => return ip.get(gpa, .{ .opt = .{ | |
| 3657 | .ty = new_ty, | |
| 3658 | .val = .none, | |
| 3659 | } }), | |
| 3660 | else => return ip.get(gpa, .{ .opt = .{ | |
| 3661 | .ty = new_ty, | |
| 3662 | .val = try ip.getCoerced(gpa, val, child_ty), | |
| 3663 | } }), | |
| 3664 | }, | |
| 3665 | else => {}, | |
| 3630 | 3666 | } |
| 3667 | unreachable; | |
| 3631 | 3668 | } |
| 3632 | 3669 | |
| 3633 | 3670 | /// Asserts `val` has an integer type. |
src/Sema.zig+10-9| ... | ... | @@ -8480,13 +8480,10 @@ fn zirOptionalPayload( |
| 8480 | 8480 | }; |
| 8481 | 8481 | |
| 8482 | 8482 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 8483 | if (val.isNull(mod)) { | |
| 8484 | return sema.fail(block, src, "unable to unwrap null", .{}); | |
| 8485 | } | |
| 8486 | if (val.castTag(.opt_payload)) |payload| { | |
| 8487 | return sema.addConstant(result_ty, payload.data); | |
| 8488 | } | |
| 8489 | return sema.addConstant(result_ty, val); | |
| 8483 | return if (val.optionalValue(mod)) |payload| | |
| 8484 | sema.addConstant(result_ty, payload) | |
| 8485 | else | |
| 8486 | sema.fail(block, src, "unable to unwrap null", .{}); | |
| 8490 | 8487 | } |
| 8491 | 8488 | |
| 8492 | 8489 | try sema.requireRuntimeBlock(block, src, null); |
| ... | ... | @@ -18929,7 +18926,7 @@ fn zirReify( |
| 18929 | 18926 | if (ptr_size == .One or ptr_size == .C) { |
| 18930 | 18927 | return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); |
| 18931 | 18928 | } |
| 18932 | const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data; | |
| 18929 | const sentinel_ptr_val = sentinel_val.optionalValue(mod).?; | |
| 18933 | 18930 | const ptr_ty = try Type.ptr(sema.arena, mod, .{ |
| 18934 | 18931 | .@"addrspace" = .generic, |
| 18935 | 18932 | .pointee_type = elem_ty, |
| ... | ... | @@ -28807,7 +28804,11 @@ fn coerceCompatiblePtrs( |
| 28807 | 28804 | return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)}); |
| 28808 | 28805 | } |
| 28809 | 28806 | // The comptime Value representation is compatible with both types. |
| 28810 | return sema.addConstant(dest_ty, val); | |
| 28807 | return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced( | |
| 28808 | mod.gpa, | |
| 28809 | try val.intern(inst_ty, mod), | |
| 28810 | dest_ty.ip_index, | |
| 28811 | )).toValue()); | |
| 28811 | 28812 | } |
| 28812 | 28813 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 28813 | 28814 | const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod); |
src/value.zig+33-17| ... | ... | @@ -718,18 +718,25 @@ pub const Value = struct { |
| 718 | 718 | }, |
| 719 | 719 | else => unreachable, |
| 720 | 720 | }; |
| 721 | const enum_type = ip.indexToKey(ty.ip_index).enum_type; | |
| 722 | if (enum_type.values.len != 0) { | |
| 723 | return enum_type.values[field_index].toValue(); | |
| 724 | } else { | |
| 725 | // Field index and integer values are the same. | |
| 726 | return mod.intValue(enum_type.tag_ty.toType(), field_index); | |
| 727 | } | |
| 721 | return switch (ip.indexToKey(ty.ip_index)) { | |
| 722 | // Assume it is already an integer and return it directly. | |
| 723 | .simple_type, .int_type => val, | |
| 724 | .enum_type => |enum_type| if (enum_type.values.len != 0) | |
| 725 | enum_type.values[field_index].toValue() | |
| 726 | else // Field index and integer values are the same. | |
| 727 | mod.intValue(enum_type.tag_ty.toType(), field_index), | |
| 728 | else => unreachable, | |
| 729 | }; | |
| 728 | 730 | }, |
| 729 | else => { | |
| 730 | const enum_type = ip.indexToKey(ip.typeOf(val.ip_index)).enum_type; | |
| 731 | const int = try ip.getCoerced(mod.gpa, val.ip_index, enum_type.tag_ty); | |
| 732 | return int.toValue(); | |
| 731 | else => return switch (ip.indexToKey(ip.typeOf(val.ip_index))) { | |
| 732 | // Assume it is already an integer and return it directly. | |
| 733 | .simple_type, .int_type => val, | |
| 734 | .enum_type => |enum_type| (try ip.getCoerced( | |
| 735 | mod.gpa, | |
| 736 | val.ip_index, | |
| 737 | enum_type.tag_ty, | |
| 738 | )).toValue(), | |
| 739 | else => unreachable, | |
| 733 | 740 | }, |
| 734 | 741 | } |
| 735 | 742 | } |
| ... | ... | @@ -2906,7 +2913,7 @@ pub const Value = struct { |
| 2906 | 2913 | inline .u64, .i64 => |x| x == 0, |
| 2907 | 2914 | }, |
| 2908 | 2915 | .opt => |opt| opt.val == .none, |
| 2909 | else => unreachable, | |
| 2916 | else => false, | |
| 2910 | 2917 | }, |
| 2911 | 2918 | }; |
| 2912 | 2919 | } |
| ... | ... | @@ -2949,11 +2956,20 @@ pub const Value = struct { |
| 2949 | 2956 | |
| 2950 | 2957 | /// Value of the optional, null if optional has no payload. |
| 2951 | 2958 | pub fn optionalValue(val: Value, mod: *const Module) ?Value { |
| 2952 | if (val.isNull(mod)) return null; | |
| 2953 | ||
| 2954 | // Valid for optional representation to be the direct value | |
| 2955 | // and not use opt_payload. | |
| 2956 | return if (val.castTag(.opt_payload)) |p| p.data else val; | |
| 2959 | return switch (val.ip_index) { | |
| 2960 | .none => if (val.isNull(mod)) null | |
| 2961 | // Valid for optional representation to be the direct value | |
| 2962 | // and not use opt_payload. | |
| 2963 | else if (val.castTag(.opt_payload)) |p| p.data else val, | |
| 2964 | .null_value => null, | |
| 2965 | else => switch (mod.intern_pool.indexToKey(val.ip_index)) { | |
| 2966 | .opt => |opt| switch (opt.val) { | |
| 2967 | .none => null, | |
| 2968 | else => opt.val.toValue(), | |
| 2969 | }, | |
| 2970 | else => unreachable, | |
| 2971 | }, | |
| 2972 | }; | |
| 2957 | 2973 | } |
| 2958 | 2974 | |
| 2959 | 2975 | /// Valid for all types. Asserts the value is not undefined. |