authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-29 07:30:30-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
log4f70863a55e699c13731325f8c52870119479c02
treec3e45219ecaf9ae0fd2ffc7316a0063028d65fce
parent32692569656d9a178abb24f8fb7893395700cb62

InternPool: fix various pointer issues


4 files changed, 102 insertions(+), 80 deletions(-)

src/InternPool.zig+78-67
...@@ -1374,12 +1374,12 @@ pub const Index = enum(u32) {...@@ -1374,12 +1374,12 @@ pub const Index = enum(u32) {
1374 undef: DataIsIndex,1374 undef: DataIsIndex,
1375 runtime_value: DataIsIndex,1375 runtime_value: DataIsIndex,
1376 simple_value: struct { data: SimpleValue },1376 simple_value: struct { data: SimpleValue },
1377 ptr_mut_decl: struct { data: *PtrMutDecl },
1378 ptr_decl: struct { data: *PtrDecl },1377 ptr_decl: struct { data: *PtrDecl },
1379 ptr_int: struct { data: *PtrAddr },1378 ptr_mut_decl: struct { data: *PtrMutDecl },
1380 ptr_eu_payload: DataIsIndex,
1381 ptr_opt_payload: DataIsIndex,
1382 ptr_comptime_field: struct { data: *PtrComptimeField },1379 ptr_comptime_field: struct { data: *PtrComptimeField },
1380 ptr_int: struct { data: *PtrBase },
1381 ptr_eu_payload: struct { data: *PtrBase },
1382 ptr_opt_payload: struct { data: *PtrBase },
1383 ptr_elem: struct { data: *PtrBaseIndex },1383 ptr_elem: struct { data: *PtrBaseIndex },
1384 ptr_field: struct { data: *PtrBaseIndex },1384 ptr_field: struct { data: *PtrBaseIndex },
1385 ptr_slice: struct { data: *PtrSlice },1385 ptr_slice: struct { data: *PtrSlice },
...@@ -1774,29 +1774,25 @@ pub const Tag = enum(u8) {...@@ -1774,29 +1774,25 @@ pub const Tag = enum(u8) {
1774 /// A value that can be represented with only an enum tag.1774 /// A value that can be represented with only an enum tag.
1775 /// data is SimpleValue enum value.1775 /// data is SimpleValue enum value.
1776 simple_value,1776 simple_value,
1777 /// A pointer to a decl that can be mutated at comptime.
1778 /// data is extra index of PtrMutDecl, which contains the type and address.
1779 ptr_mut_decl,
1780 /// A pointer to a decl.1777 /// A pointer to a decl.
1781 /// data is extra index of PtrDecl, which contains the type and address.1778 /// data is extra index of `PtrDecl`, which contains the type and address.
1782 ptr_decl,1779 ptr_decl,
1780 /// A pointer to a decl that can be mutated at comptime.
1781 /// data is extra index of `PtrMutDecl`, which contains the type and address.
1782 ptr_mut_decl,
1783 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
1784 ptr_comptime_field,
1783 /// A pointer with an integer value.1785 /// A pointer with an integer value.
1784 /// data is extra index of PtrAddr, which contains the type and address.1786 /// data is extra index of `PtrBase`, which contains the type and address.
1785 /// Only pointer types are allowed to have this encoding. Optional types must use1787 /// Only pointer types are allowed to have this encoding. Optional types must use
1786 /// `opt_payload` or `opt_null`.1788 /// `opt_payload` or `opt_null`.
1787 ptr_int,1789 ptr_int,
1788 /// A pointer to the payload of an error union.1790 /// A pointer to the payload of an error union.
1789 /// data is Index of a pointer value to the error union.1791 /// data is extra index of `PtrBase`, which contains the type and base pointer.
1790 /// In order to use this encoding, one must ensure that the `InternPool`
1791 /// already contains the payload pointer type corresponding to this payload.
1792 ptr_eu_payload,1792 ptr_eu_payload,
1793 /// A pointer to the payload of an optional.1793 /// A pointer to the payload of an optional.
1794 /// data is Index of a pointer value to the optional.1794 /// data is extra index of `PtrBase`, which contains the type and base pointer.
1795 /// In order to use this encoding, one must ensure that the `InternPool`
1796 /// already contains the payload pointer type corresponding to this payload.
1797 ptr_opt_payload,1795 ptr_opt_payload,
1798 /// data is extra index of PtrComptimeField, which contains the pointer type and field value.
1799 ptr_comptime_field,
1800 /// A pointer to an array element.1796 /// A pointer to an array element.
1801 /// data is extra index of PtrBaseIndex, which contains the base array and element index.1797 /// data is extra index of PtrBaseIndex, which contains the base array and element index.
1802 /// In order to use this encoding, one must ensure that the `InternPool`1798 /// In order to use this encoding, one must ensure that the `InternPool`
...@@ -2224,14 +2220,14 @@ pub const PtrMutDecl = struct {...@@ -2224,14 +2220,14 @@ pub const PtrMutDecl = struct {
2224 runtime_index: RuntimeIndex,2220 runtime_index: RuntimeIndex,
2225};2221};
22262222
2227pub const PtrAddr = struct {2223pub const PtrComptimeField = struct {
2228 ty: Index,2224 ty: Index,
2229 addr: Index,2225 field_val: Index,
2230};2226};
22312227
2232pub const PtrComptimeField = struct {2228pub const PtrBase = struct {
2233 ty: Index,2229 ty: Index,
2234 field_val: Index,2230 base: Index,
2235};2231};
22362232
2237pub const PtrBaseIndex = struct {2233pub const PtrBaseIndex = struct {
...@@ -2598,36 +2594,23 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2598,36 +2594,23 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2598 } },2594 } },
2599 } };2595 } };
2600 },2596 },
2601 .ptr_int => {2597 .ptr_comptime_field => {
2602 const info = ip.extraData(PtrAddr, data);2598 const info = ip.extraData(PtrComptimeField, data);
2603 return .{ .ptr = .{2599 return .{ .ptr = .{
2604 .ty = info.ty,2600 .ty = info.ty,
2605 .addr = .{ .int = info.addr },2601 .addr = .{ .comptime_field = info.field_val },
2606 } };
2607 },
2608 .ptr_eu_payload => {
2609 const ptr_eu_index = @intToEnum(Index, data);
2610 var ptr_type = ip.indexToKey(ip.typeOf(ptr_eu_index)).ptr_type;
2611 ptr_type.elem_type = ip.indexToKey(ptr_type.elem_type).error_union_type.payload_type;
2612 return .{ .ptr = .{
2613 .ty = ip.getAssumeExists(.{ .ptr_type = ptr_type }),
2614 .addr = .{ .eu_payload = ptr_eu_index },
2615 } };2602 } };
2616 },2603 },
2617 .ptr_opt_payload => {2604 .ptr_int, .ptr_eu_payload, .ptr_opt_payload => {
2618 const ptr_opt_index = @intToEnum(Index, data);2605 const info = ip.extraData(PtrBase, data);
2619 var ptr_type = ip.indexToKey(ip.typeOf(ptr_opt_index)).ptr_type;
2620 ptr_type.elem_type = ip.indexToKey(ptr_type.elem_type).opt_type;
2621 return .{ .ptr = .{
2622 .ty = ip.getAssumeExists(.{ .ptr_type = ptr_type }),
2623 .addr = .{ .opt_payload = ptr_opt_index },
2624 } };
2625 },
2626 .ptr_comptime_field => {
2627 const info = ip.extraData(PtrComptimeField, data);
2628 return .{ .ptr = .{2606 return .{ .ptr = .{
2629 .ty = info.ty,2607 .ty = info.ty,
2630 .addr = .{ .comptime_field = info.field_val },2608 .addr = switch (item.tag) {
2609 .ptr_int => .{ .int = info.base },
2610 .ptr_eu_payload => .{ .eu_payload = info.base },
2611 .ptr_opt_payload => .{ .opt_payload = info.base },
2612 else => unreachable,
2613 },
2631 } };2614 } };
2632 },2615 },
2633 .ptr_elem => {2616 .ptr_elem => {
...@@ -3248,39 +3231,67 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3248,39 +3231,67 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3248 .runtime_index = mut_decl.runtime_index,3231 .runtime_index = mut_decl.runtime_index,
3249 }),3232 }),
3250 }),3233 }),
3251 .int => |int| {3234 .comptime_field => |field_val| {
3252 assert(ip.typeOf(int) == .usize_type);3235 assert(field_val != .none);
3253 ip.items.appendAssumeCapacity(.{3236 ip.items.appendAssumeCapacity(.{
3254 .tag = .ptr_int,3237 .tag = .ptr_comptime_field,
3255 .data = try ip.addExtra(gpa, PtrAddr{3238 .data = try ip.addExtra(gpa, PtrComptimeField{
3256 .ty = ptr.ty,3239 .ty = ptr.ty,
3257 .addr = int,3240 .field_val = field_val,
3258 }),3241 }),
3259 });3242 });
3260 },3243 },
3261 .eu_payload, .opt_payload => |data| {3244 .int, .eu_payload, .opt_payload => |base| {
3262 assert(data != .none);3245 switch (ptr.addr) {
3246 .int => assert(ip.typeOf(base) == .usize_type),
3247 .eu_payload => assert(ip.indexToKey(
3248 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
3249 ) == .error_union_type),
3250 .opt_payload => assert(ip.indexToKey(
3251 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
3252 ) == .opt_type),
3253 else => unreachable,
3254 }
3263 ip.items.appendAssumeCapacity(.{3255 ip.items.appendAssumeCapacity(.{
3264 .tag = switch (ptr.addr) {3256 .tag = switch (ptr.addr) {
3257 .int => .ptr_int,
3265 .eu_payload => .ptr_eu_payload,3258 .eu_payload => .ptr_eu_payload,
3266 .opt_payload => .ptr_opt_payload,3259 .opt_payload => .ptr_opt_payload,
3267 else => unreachable,3260 else => unreachable,
3268 },3261 },
3269 .data = @enumToInt(data),3262 .data = try ip.addExtra(gpa, PtrBase{
3270 });
3271 },
3272 .comptime_field => |field_val| {
3273 assert(field_val != .none);
3274 ip.items.appendAssumeCapacity(.{
3275 .tag = .ptr_comptime_field,
3276 .data = try ip.addExtra(gpa, PtrComptimeField{
3277 .ty = ptr.ty,3263 .ty = ptr.ty,
3278 .field_val = field_val,3264 .base = base,
3279 }),3265 }),
3280 });3266 });
3281 },3267 },
3282 .elem, .field => |base_index| {3268 .elem, .field => |base_index| {
3283 assert(base_index.base != .none);3269 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
3270 switch (base_ptr_type.size) {
3271 .One => switch (ip.indexToKey(base_ptr_type.elem_type)) {
3272 .array_type, .vector_type => assert(ptr.addr == .elem),
3273 .anon_struct_type => |anon_struct_type| {
3274 assert(ptr.addr == .field);
3275 assert(base_index.index < anon_struct_type.types.len);
3276 },
3277 .struct_type => |struct_type| {
3278 assert(ptr.addr == .field);
3279 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
3280 },
3281 .union_type => |union_type| {
3282 assert(ptr.addr == .field);
3283 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
3284 },
3285 .ptr_type => |slice_type| {
3286 assert(ptr.addr == .field);
3287 assert(slice_type.size == .Slice);
3288 assert(base_index.index < 2);
3289 },
3290 else => unreachable,
3291 },
3292 .Many => assert(ptr.addr == .elem),
3293 .Slice, .C => unreachable,
3294 }
3284 _ = ip.map.pop();3295 _ = ip.map.pop();
3285 const index_index = try ip.get(gpa, .{ .int = .{3296 const index_index = try ip.get(gpa, .{ .int = .{
3286 .ty = .usize_type,3297 .ty = .usize_type,
...@@ -4750,10 +4761,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -4750,10 +4761,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
4750 .simple_value => 0,4761 .simple_value => 0,
4751 .ptr_decl => @sizeOf(PtrDecl),4762 .ptr_decl => @sizeOf(PtrDecl),
4752 .ptr_mut_decl => @sizeOf(PtrMutDecl),4763 .ptr_mut_decl => @sizeOf(PtrMutDecl),
4753 .ptr_int => @sizeOf(PtrAddr),
4754 .ptr_eu_payload => 0,
4755 .ptr_opt_payload => 0,
4756 .ptr_comptime_field => @sizeOf(PtrComptimeField),4764 .ptr_comptime_field => @sizeOf(PtrComptimeField),
4765 .ptr_int => @sizeOf(PtrBase),
4766 .ptr_eu_payload => @sizeOf(PtrBase),
4767 .ptr_opt_payload => @sizeOf(PtrBase),
4757 .ptr_elem => @sizeOf(PtrBaseIndex),4768 .ptr_elem => @sizeOf(PtrBaseIndex),
4758 .ptr_field => @sizeOf(PtrBaseIndex),4769 .ptr_field => @sizeOf(PtrBaseIndex),
4759 .ptr_slice => @sizeOf(PtrSlice),4770 .ptr_slice => @sizeOf(PtrSlice),
...@@ -5281,12 +5292,12 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std...@@ -5281,12 +5292,12 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std
5281 .undef,5292 .undef,
5282 .runtime_value,5293 .runtime_value,
5283 .simple_value,5294 .simple_value,
5284 .ptr_mut_decl,
5285 .ptr_decl,5295 .ptr_decl,
5296 .ptr_mut_decl,
5297 .ptr_comptime_field,
5286 .ptr_int,5298 .ptr_int,
5287 .ptr_eu_payload,5299 .ptr_eu_payload,
5288 .ptr_opt_payload,5300 .ptr_opt_payload,
5289 .ptr_comptime_field,
5290 .ptr_elem,5301 .ptr_elem,
5291 .ptr_field,5302 .ptr_field,
5292 .ptr_slice,5303 .ptr_slice,
src/Module.zig+4
...@@ -6716,6 +6716,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {...@@ -6716,6 +6716,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6716 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .is_const = true });6716 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .is_const = true });
6717}6717}
67186718
6719pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6720 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .size = .Many, .is_const = true });
6721}
6722
6719pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {6723pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
6720 const info = Type.ptrInfoIp(mod.intern_pool, ptr_ty.toIntern());6724 const info = Type.ptrInfoIp(mod.intern_pool, ptr_ty.toIntern());
6721 return mod.ptrType(.{6725 return mod.ptrType(.{
src/Sema.zig+17-12
...@@ -25412,11 +25412,13 @@ fn elemVal(...@@ -25412,11 +25412,13 @@ fn elemVal(
25412 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;25412 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
25413 const index_val = maybe_index_val orelse break :rs elem_index_src;25413 const index_val = maybe_index_val orelse break :rs elem_index_src;
25414 const index = @intCast(usize, index_val.toUnsignedInt(mod));25414 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25415 const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index);25415 const elem_ty = indexable_ty.elemType2(mod);
25416 const elem_ptr_val = try indexable_val.elemPtr(elem_ptr_ty, index, mod);25416 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
25417 const many_ptr_val = try mod.getCoerced(indexable_val, many_ptr_ty);
25418 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
25419 const elem_ptr_val = try many_ptr_val.elemPtr(elem_ptr_ty, index, mod);
25417 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {25420 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
25418 const result_ty = indexable_ty.elemType2(mod);25421 return sema.addConstant(elem_ty, try mod.getCoerced(elem_val, elem_ty));
25419 return sema.addConstant(result_ty, try mod.getCoerced(elem_val, result_ty));
25420 }25422 }
25421 break :rs indexable_src;25423 break :rs indexable_src;
25422 };25424 };
...@@ -29906,7 +29908,7 @@ fn analyzeSlice(...@@ -29906,7 +29908,7 @@ fn analyzeSlice(
29906 const ptr_ptr_ty = sema.typeOf(ptr_ptr);29908 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
29907 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) {29909 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) {
29908 .Pointer => ptr_ptr_ty.childType(mod),29910 .Pointer => ptr_ptr_ty.childType(mod),
29909 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}),29911 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(mod)}),
29910 };29912 };
2991129913
29912 var array_ty = ptr_ptr_child_ty;29914 var array_ty = ptr_ptr_child_ty;
...@@ -30111,7 +30113,10 @@ fn analyzeSlice(...@@ -30111,7 +30113,10 @@ fn analyzeSlice(
30111 const end_int = end_val.getUnsignedInt(mod).?;30113 const end_int = end_val.getUnsignedInt(mod).?;
30112 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);30114 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
3011330115
30114 const elem_ptr = try ptr_val.elemPtr(try sema.elemPtrType(new_ptr_ty, sentinel_index), sentinel_index, sema.mod);30116 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
30117 const many_ptr_val = try mod.getCoerced(ptr_val, many_ptr_ty);
30118 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
30119 const elem_ptr = try many_ptr_val.elemPtr(elem_ptr_ty, sentinel_index, mod);
30115 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty);30120 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty);
30116 const actual_sentinel = switch (res) {30121 const actual_sentinel = switch (res) {
30117 .runtime_load => break :sentinel_check,30122 .runtime_load => break :sentinel_check,
...@@ -30120,23 +30125,23 @@ fn analyzeSlice(...@@ -30120,23 +30125,23 @@ fn analyzeSlice(
30120 block,30125 block,
30121 src,30126 src,
30122 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",30127 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",
30123 .{ty.fmt(sema.mod)},30128 .{ty.fmt(mod)},
30124 ),30129 ),
30125 .out_of_bounds => |ty| return sema.fail(30130 .out_of_bounds => |ty| return sema.fail(
30126 block,30131 block,
30127 end_src,30132 end_src,
30128 "slice end index {d} exceeds bounds of containing decl of type '{}'",30133 "slice end index {d} exceeds bounds of containing decl of type '{}'",
30129 .{ end_int, ty.fmt(sema.mod) },30134 .{ end_int, ty.fmt(mod) },
30130 ),30135 ),
30131 };30136 };
3013230137
30133 if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) {30138 if (!actual_sentinel.eql(expected_sentinel, elem_ty, mod)) {
30134 const msg = msg: {30139 const msg = msg: {
30135 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});30140 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
30136 errdefer msg.destroy(sema.gpa);30141 errdefer msg.destroy(sema.gpa);
30137 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{30142 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
30138 expected_sentinel.fmtValue(elem_ty, sema.mod),30143 expected_sentinel.fmtValue(elem_ty, mod),
30139 actual_sentinel.fmtValue(elem_ty, sema.mod),30144 actual_sentinel.fmtValue(elem_ty, mod),
30140 });30145 });
3014130146
30142 break :msg msg;30147 break :msg msg;
...@@ -30310,7 +30315,7 @@ fn cmpNumeric(...@@ -30310,7 +30315,7 @@ fn cmpNumeric(
3031030315
30311 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);30316 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
30312 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);30317 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
30313 const target = sema.mod.getTarget();30318 const target = mod.getTarget();
3031430319
30315 // One exception to heterogeneous comparison: comptime_float needs to30320 // One exception to heterogeneous comparison: comptime_float needs to
30316 // coerce to fixed-width float.30321 // coerce to fixed-width float.
src/value.zig+3-1
...@@ -1857,7 +1857,8 @@ pub const Value = struct {...@@ -1857,7 +1857,8 @@ pub const Value = struct {
1857 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),1857 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
1858 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))1858 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
1859 .toValue().elemValue(mod, index),1859 .toValue().elemValue(mod, index),
1860 .int, .eu_payload, .opt_payload => unreachable,1860 .int, .eu_payload => unreachable,
1861 .opt_payload => |base| base.toValue().elemValue(mod, index),
1861 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),1862 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
1862 .elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),1863 .elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),
1863 .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {1864 .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {
...@@ -1866,6 +1867,7 @@ pub const Value = struct {...@@ -1866,6 +1867,7 @@ pub const Value = struct {
1866 return field_val.elemValue(mod, index);1867 return field_val.elemValue(mod, index);
1867 } else unreachable,1868 } else unreachable,
1868 },1869 },
1870 .opt => |opt| opt.val.toValue().elemValue(mod, index),
1869 .aggregate => |aggregate| {1871 .aggregate => |aggregate| {
1870 const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);1872 const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);
1871 if (index < len) return switch (aggregate.storage) {1873 if (index < len) return switch (aggregate.storage) {