authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-21 03:57:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:54-07:00
logbe1b23120648dff5e23d67b089c10b479564bffd
tree79e455747856a29c096ee4f5e5ef61e7186b57c2
parent9584feae5f27a8b987975d8fe8242e2169098a75

InternPool: add missing logic


3 files changed, 84 insertions(+), 30 deletions(-)

src/InternPool.zig+41-4
......@@ -1517,6 +1517,8 @@ pub const Tag = enum(u8) {
15171517/// 0. name: NullTerminatedString for each names_len
15181518pub const ErrorSet = struct {
15191519 names_len: u32,
1520 /// Maps error names to declaration index.
1521 names_map: MapIndex,
15201522};
15211523
15221524/// Trailing:
......@@ -2024,6 +2026,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
20242026 const names = ip.extra.items[error_set.end..][0..names_len];
20252027 return .{ .error_set_type = .{
20262028 .names = @ptrCast([]const NullTerminatedString, names),
2029 .names_map = error_set.data.names_map.toOptional(),
20272030 } };
20282031 },
20292032 .type_inferred_error_set => .{
......@@ -2518,6 +2521,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
25182521 .tag = .type_error_set,
25192522 .data = ip.addExtraAssumeCapacity(ErrorSet{
25202523 .names_len = names_len,
2524 .names_map = names_map,
25212525 }),
25222526 });
25232527 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names));
......@@ -3605,15 +3609,34 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
36053609/// * int <=> int
36063610/// * int <=> enum
36073611/// * ptr <=> ptr
3612/// * null_value => opt
3613/// * payload => opt
36083614pub 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;
36103617 switch (ip.indexToKey(val)) {
36113618 .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),
36123635 .enum_type => return ip.get(gpa, .{ .enum_tag = .{
36133636 .ty = new_ty,
36143637 .int = val,
36153638 } }),
3616 else => return getCoercedInts(ip, gpa, int, new_ty),
3639 else => {},
36173640 },
36183641 .enum_tag => |enum_tag| {
36193642 // Assume new_ty is an integer type.
......@@ -3624,10 +3647,24 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
36243647 .ty = new_ty,
36253648 .addr = ptr.addr,
36263649 } }),
3627 else => unreachable,
3650 else => {},
36283651 },
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 => {},
36303666 }
3667 unreachable;
36313668}
36323669
36333670/// Asserts `val` has an integer type.
src/Sema.zig+10-9
......@@ -8480,13 +8480,10 @@ fn zirOptionalPayload(
84808480 };
84818481
84828482 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", .{});
84908487 }
84918488
84928489 try sema.requireRuntimeBlock(block, src, null);
......@@ -18929,7 +18926,7 @@ fn zirReify(
1892918926 if (ptr_size == .One or ptr_size == .C) {
1893018927 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
1893118928 }
18932 const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;
18929 const sentinel_ptr_val = sentinel_val.optionalValue(mod).?;
1893318930 const ptr_ty = try Type.ptr(sema.arena, mod, .{
1893418931 .@"addrspace" = .generic,
1893518932 .pointee_type = elem_ty,
......@@ -28807,7 +28804,11 @@ fn coerceCompatiblePtrs(
2880728804 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
2880828805 }
2880928806 // 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());
2881128812 }
2881228813 try sema.requireRuntimeBlock(block, inst_src, null);
2881328814 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 {
718718 },
719719 else => unreachable,
720720 };
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 };
728730 },
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,
733740 },
734741 }
735742 }
......@@ -2906,7 +2913,7 @@ pub const Value = struct {
29062913 inline .u64, .i64 => |x| x == 0,
29072914 },
29082915 .opt => |opt| opt.val == .none,
2909 else => unreachable,
2916 else => false,
29102917 },
29112918 };
29122919 }
......@@ -2949,11 +2956,20 @@ pub const Value = struct {
29492956
29502957 /// Value of the optional, null if optional has no payload.
29512958 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 };
29572973 }
29582974
29592975 /// Valid for all types. Asserts the value is not undefined.