authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-17 03:34:47+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-06 21:26:37+00:00
log8ec6f730eff1f6008b7eba1c749824a4a5734e5f
tree34cf9c0ef9ab1d5ee6338984440deb1db1d7ec2e
parent975b859377dee450418ae9ed572ec9d3c0b77312
signaturelock-open Commit is signed but in an unrecognized format.

compiler: represent captures directly in InternPool

These were previously associated with the type's namespace, but we need to store them directly in the InternPool for #18816.

4 files changed, 356 insertions(+), 132 deletions(-)

src/InternPool.zig+320-79
......@@ -501,6 +501,42 @@ pub const OptionalNullTerminatedString = enum(u32) {
501501 }
502502};
503503
504/// A single value captured in the closure of a namespace type. This is not a plain
505/// `Index` because we must differentiate between runtime-known values (where we
506/// store the type) and comptime-known values (where we store the value).
507pub const CaptureValue = packed struct(u32) {
508 tag: enum { @"comptime", runtime },
509 idx: u31,
510
511 pub fn wrap(val: Unwrapped) CaptureValue {
512 return switch (val) {
513 .@"comptime" => |i| .{ .tag = .@"comptime", .idx = @intCast(@intFromEnum(i)) },
514 .runtime => |i| .{ .tag = .runtime, .idx = @intCast(@intFromEnum(i)) },
515 };
516 }
517 pub fn unwrap(val: CaptureValue) Unwrapped {
518 return switch (val.tag) {
519 .@"comptime" => .{ .@"comptime" = @enumFromInt(val.idx) },
520 .runtime => .{ .runtime = @enumFromInt(val.idx) },
521 };
522 }
523
524 pub const Unwrapped = union(enum) {
525 /// Index refers to the value.
526 @"comptime": Index,
527 /// Index refers to the type.
528 runtime: Index,
529 };
530
531 pub const Slice = struct {
532 start: u32,
533 len: u32,
534 pub fn get(slice: Slice, ip: *const InternPool) []CaptureValue {
535 return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
536 }
537 };
538};
539
504540pub const Key = union(enum) {
505541 int_type: IntType,
506542 ptr_type: PtrType,
......@@ -707,6 +743,7 @@ pub const Key = union(enum) {
707743 /// This may be updated via `setTagType` later.
708744 tag_ty: Index = .none,
709745 zir_index: TrackedInst.Index.Optional,
746 captures: []const CaptureValue,
710747
711748 pub fn toEnumType(self: @This()) LoadedEnumType {
712749 if (true) @compileError("AHHHH");
......@@ -1660,6 +1697,7 @@ pub const LoadedUnionType = struct {
16601697 field_aligns: Alignment.Slice,
16611698 /// Index of the union_decl ZIR instruction.
16621699 zir_index: TrackedInst.Index.Optional,
1700 captures: CaptureValue.Slice,
16631701
16641702 pub const RuntimeTag = enum(u2) {
16651703 none,
......@@ -1791,24 +1829,47 @@ pub const LoadedUnionType = struct {
17911829};
17921830
17931831pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
1794 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
1795 const type_union = ip.extraDataTrail(Tag.TypeUnion, extra_index);
1832 const data = ip.items.items(.data)[@intFromEnum(index)];
1833 const type_union = ip.extraDataTrail(Tag.TypeUnion, data);
17961834 const fields_len = type_union.data.fields_len;
17971835
1836 var extra_index = type_union.end;
1837 const captures_len = if (type_union.data.flags.any_captures) c: {
1838 const len = ip.extra.items[extra_index];
1839 extra_index += 1;
1840 break :c len;
1841 } else 0;
1842
1843 const captures: CaptureValue.Slice = .{
1844 .start = extra_index,
1845 .len = captures_len,
1846 };
1847 extra_index += captures_len;
1848
1849 const field_types: Index.Slice = .{
1850 .start = extra_index,
1851 .len = fields_len,
1852 };
1853 extra_index += fields_len;
1854
1855 const field_aligns: Alignment.Slice = if (type_union.data.flags.any_aligned_fields) a: {
1856 const a: Alignment.Slice = .{
1857 .start = extra_index,
1858 .len = fields_len,
1859 };
1860 extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;
1861 break :a a;
1862 } else .{ .start = 0, .len = 0 };
1863
17981864 return .{
1799 .extra_index = extra_index,
1865 .extra_index = data,
18001866 .decl = type_union.data.decl,
18011867 .namespace = type_union.data.namespace,
18021868 .enum_tag_ty = type_union.data.tag_ty,
1803 .field_types = .{
1804 .start = type_union.end,
1805 .len = fields_len,
1806 },
1807 .field_aligns = .{
1808 .start = type_union.end + fields_len,
1809 .len = if (type_union.data.flags.any_aligned_fields) fields_len else 0,
1810 },
1869 .field_types = field_types,
1870 .field_aligns = field_aligns,
18111871 .zir_index = type_union.data.zir_index,
1872 .captures = captures,
18121873 };
18131874}
18141875
......@@ -1830,6 +1891,7 @@ pub const LoadedStructType = struct {
18301891 comptime_bits: ComptimeBits,
18311892 offsets: Offsets,
18321893 names_map: OptionalMapIndex,
1894 captures: CaptureValue.Slice,
18331895
18341896 pub const ComptimeBits = struct {
18351897 start: u32,
......@@ -2162,10 +2224,26 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
21622224 .comptime_bits = .{ .start = 0, .len = 0 },
21632225 .offsets = .{ .start = 0, .len = 0 },
21642226 .names_map = .none,
2227 .captures = .{ .start = 0, .len = 0 },
21652228 };
21662229 const extra = ip.extraDataTrail(Tag.TypeStruct, item.data);
21672230 const fields_len = extra.data.fields_len;
2168 var extra_index = extra.end + fields_len; // skip field types
2231 var extra_index = extra.end;
2232 const captures_len = if (extra.data.flags.any_captures) c: {
2233 const len = ip.extra.items[extra_index];
2234 extra_index += 1;
2235 break :c len;
2236 } else 0;
2237 const captures: CaptureValue.Slice = .{
2238 .start = extra_index,
2239 .len = captures_len,
2240 };
2241 extra_index += captures_len;
2242 const field_types: Index.Slice = .{
2243 .start = extra_index,
2244 .len = fields_len,
2245 };
2246 extra_index += fields_len;
21692247 const names_map: OptionalMapIndex, const names: NullTerminatedString.Slice = if (!extra.data.flags.is_tuple) n: {
21702248 const names_map: OptionalMapIndex = @enumFromInt(ip.extra.items[extra_index]);
21712249 extra_index += 1;
......@@ -2211,42 +2289,64 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
22112289 .zir_index = extra.data.zir_index,
22122290 .layout = if (extra.data.flags.is_extern) .Extern else .Auto,
22132291 .field_names = names,
2214 .field_types = .{ .start = extra.end, .len = fields_len },
2292 .field_types = field_types,
22152293 .field_inits = inits,
22162294 .field_aligns = aligns,
22172295 .runtime_order = runtime_order,
22182296 .comptime_bits = comptime_bits,
22192297 .offsets = offsets,
22202298 .names_map = names_map,
2299 .captures = captures,
22212300 };
22222301 },
22232302 .type_struct_packed, .type_struct_packed_inits => {
22242303 const extra = ip.extraDataTrail(Tag.TypeStructPacked, item.data);
22252304 const has_inits = item.tag == .type_struct_packed_inits;
22262305 const fields_len = extra.data.fields_len;
2306 var extra_index = extra.end;
2307 const captures_len = if (extra.data.flags.any_captures) c: {
2308 const len = ip.extra.items[extra_index];
2309 extra_index += 1;
2310 break :c len;
2311 } else 0;
2312 const captures: CaptureValue.Slice = .{
2313 .start = extra_index,
2314 .len = captures_len,
2315 };
2316 extra_index += captures_len;
2317 const field_types: Index.Slice = .{
2318 .start = extra_index,
2319 .len = fields_len,
2320 };
2321 extra_index += fields_len;
2322 const field_names: NullTerminatedString.Slice = .{
2323 .start = extra_index,
2324 .len = fields_len,
2325 };
2326 extra_index += fields_len;
2327 const field_inits: Index.Slice = if (has_inits) inits: {
2328 const i: Index.Slice = .{
2329 .start = extra_index,
2330 .len = fields_len,
2331 };
2332 extra_index += fields_len;
2333 break :inits i;
2334 } else .{ .start = 0, .len = 0 };
22272335 return .{
22282336 .extra_index = item.data,
22292337 .decl = extra.data.decl.toOptional(),
22302338 .namespace = extra.data.namespace,
22312339 .zir_index = extra.data.zir_index,
22322340 .layout = .Packed,
2233 .field_names = .{
2234 .start = extra.end + fields_len,
2235 .len = fields_len,
2236 },
2237 .field_types = .{
2238 .start = extra.end,
2239 .len = fields_len,
2240 },
2241 .field_inits = if (has_inits) .{
2242 .start = extra.end + 2 * fields_len,
2243 .len = fields_len,
2244 } else .{ .start = 0, .len = 0 },
2341 .field_names = field_names,
2342 .field_types = field_types,
2343 .field_inits = field_inits,
22452344 .field_aligns = .{ .start = 0, .len = 0 },
22462345 .runtime_order = .{ .start = 0, .len = 0 },
22472346 .comptime_bits = .{ .start = 0, .len = 0 },
22482347 .offsets = .{ .start = 0, .len = 0 },
22492348 .names_map = extra.data.names_map.toOptional(),
2349 .captures = captures,
22502350 };
22512351 },
22522352 else => unreachable,
......@@ -2273,6 +2373,7 @@ const LoadedEnumType = struct {
22732373 /// This is guaranteed to not be `.none` if explicit values are provided.
22742374 values_map: OptionalMapIndex,
22752375 zir_index: TrackedInst.Index.Optional,
2376 captures: CaptureValue.Slice,
22762377
22772378 pub const TagMode = enum {
22782379 /// The integer tag type was auto-numbered by zig.
......@@ -2332,7 +2433,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
23322433 .namespace = extra.data.namespace,
23332434 .tag_ty = extra.data.int_tag_type,
23342435 .names = .{
2335 .start = @intCast(extra.end),
2436 .start = @intCast(extra.end + extra.data.captures_len),
23362437 .len = extra.data.fields_len,
23372438 },
23382439 .values = .{ .start = 0, .len = 0 },
......@@ -2340,6 +2441,10 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
23402441 .names_map = extra.data.names_map,
23412442 .values_map = .none,
23422443 .zir_index = extra.data.zir_index,
2444 .captures = .{
2445 .start = @intCast(extra.end),
2446 .len = extra.data.captures_len,
2447 },
23432448 };
23442449 },
23452450 .type_enum_explicit, .type_enum_nonexhaustive => {
......@@ -2349,11 +2454,11 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
23492454 .namespace = extra.data.namespace,
23502455 .tag_ty = extra.data.int_tag_type,
23512456 .names = .{
2352 .start = @intCast(extra.end),
2457 .start = @intCast(extra.end + extra.data.captures_len),
23532458 .len = extra.data.fields_len,
23542459 },
23552460 .values = .{
2356 .start = @intCast(extra.end + extra.data.fields_len),
2461 .start = @intCast(extra.end + extra.data.captures_len + extra.data.fields_len),
23572462 .len = if (extra.data.values_map != .none) extra.data.fields_len else 0,
23582463 },
23592464 .tag_mode = switch (item.tag) {
......@@ -2364,6 +2469,10 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
23642469 .names_map = extra.data.names_map,
23652470 .values_map = extra.data.values_map,
23662471 .zir_index = extra.data.zir_index,
2472 .captures = .{
2473 .start = @intCast(extra.end),
2474 .len = extra.data.captures_len,
2475 },
23672476 };
23682477 },
23692478 else => unreachable,
......@@ -2378,12 +2487,22 @@ pub const LoadedOpaqueType = struct {
23782487 namespace: NamespaceIndex,
23792488 /// The index of the `opaque_decl` instruction.
23802489 zir_index: TrackedInst.Index.Optional,
2490 captures: CaptureValue.Slice,
23812491};
23822492
23832493pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
23842494 assert(ip.items.items(.tag)[@intFromEnum(index)] == .type_opaque);
23852495 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
2386 return ip.extraData(LoadedOpaqueType, extra_index);
2496 const extra = ip.extraDataTrail(Tag.TypeOpaque, extra_index);
2497 return .{
2498 .decl = extra.data.decl,
2499 .namespace = extra.data.namespace,
2500 .zir_index = extra.data.zir_index,
2501 .captures = .{
2502 .start = extra.end,
2503 .len = extra.data.captures_len,
2504 },
2505 };
23872506}
23882507
23892508pub const Item = struct {
......@@ -2601,7 +2720,7 @@ pub const Index = enum(u32) {
26012720 type_enum_explicit: DataIsExtraIndexOfEnumExplicit,
26022721 type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,
26032722 simple_type: struct { data: SimpleType },
2604 type_opaque: struct { data: *Key.OpaqueType },
2723 type_opaque: struct { data: *Tag.TypeOpaque },
26052724 type_struct: struct { data: *Tag.TypeStruct },
26062725 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
26072726 type_struct_packed: struct { data: *Tag.TypeStructPacked },
......@@ -3036,7 +3155,7 @@ pub const Tag = enum(u8) {
30363155 /// data is SimpleType enum value.
30373156 simple_type,
30383157 /// An opaque type.
3039 /// data is index of Key.OpaqueType in extra.
3158 /// data is index of Tag.TypeOpaque in extra.
30403159 type_opaque,
30413160 /// A non-packed struct type.
30423161 /// data is 0 or extra index of `TypeStruct`.
......@@ -3239,7 +3358,6 @@ pub const Tag = enum(u8) {
32393358 memoized_call,
32403359
32413360 const ErrorUnionType = Key.ErrorUnionType;
3242 const OpaqueType = LoadedOpaqueType;
32433361 const TypeValue = Key.TypeValue;
32443362 const Error = Key.Error;
32453363 const EnumTag = Key.EnumTag;
......@@ -3266,7 +3384,7 @@ pub const Tag = enum(u8) {
32663384 .type_enum_explicit => EnumExplicit,
32673385 .type_enum_nonexhaustive => EnumExplicit,
32683386 .simple_type => unreachable,
3269 .type_opaque => OpaqueType,
3387 .type_opaque => TypeOpaque,
32703388 .type_struct => TypeStruct,
32713389 .type_struct_anon => TypeStructAnon,
32723390 .type_struct_packed, .type_struct_packed_inits => TypeStructPacked,
......@@ -3424,8 +3542,10 @@ pub const Tag = enum(u8) {
34243542 };
34253543
34263544 /// Trailing:
3427 /// 0. field type: Index for each field; declaration order
3428 /// 1. field align: Alignment for each field; declaration order
3545 /// 0. captures_len: u32 // if `any_captures`
3546 /// 1. capture: CaptureValue // for each `captures_len`
3547 /// 2. field type: Index for each field; declaration order
3548 /// 3. field align: Alignment for each field; declaration order
34293549 pub const TypeUnion = struct {
34303550 flags: Flags,
34313551 /// This could be provided through the tag type, but it is more convenient
......@@ -3443,6 +3563,7 @@ pub const Tag = enum(u8) {
34433563 zir_index: TrackedInst.Index.Optional,
34443564
34453565 pub const Flags = packed struct(u32) {
3566 any_captures: bool,
34463567 runtime_tag: LoadedUnionType.RuntimeTag,
34473568 /// If false, the field alignment trailing data is omitted.
34483569 any_aligned_fields: bool,
......@@ -3452,14 +3573,16 @@ pub const Tag = enum(u8) {
34523573 assumed_runtime_bits: bool,
34533574 assumed_pointer_aligned: bool,
34543575 alignment: Alignment,
3455 _: u14 = 0,
3576 _: u13 = 0,
34563577 };
34573578 };
34583579
34593580 /// Trailing:
3460 /// 0. type: Index for each fields_len
3461 /// 1. name: NullTerminatedString for each fields_len
3462 /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
3581 /// 0. captures_len: u32 // if `any_captures`
3582 /// 1. capture: CaptureValue // for each `captures_len`
3583 /// 2. type: Index for each fields_len
3584 /// 3. name: NullTerminatedString for each fields_len
3585 /// 4. init: Index for each fields_len // if tag is type_struct_packed_inits
34633586 pub const TypeStructPacked = struct {
34643587 decl: DeclIndex,
34653588 zir_index: TrackedInst.Index.Optional,
......@@ -3470,10 +3593,11 @@ pub const Tag = enum(u8) {
34703593 flags: Flags,
34713594
34723595 pub const Flags = packed struct(u32) {
3596 any_captures: bool,
34733597 /// Dependency loop detection when resolving field inits.
34743598 field_inits_wip: bool,
34753599 inits_resolved: bool,
3476 _: u30 = 0,
3600 _: u29 = 0,
34773601 };
34783602 };
34793603
......@@ -3492,21 +3616,23 @@ pub const Tag = enum(u8) {
34923616 /// than coming up with some other scheme for the data.
34933617 ///
34943618 /// Trailing:
3495 /// 0. type: Index for each field in declared order
3496 /// 1. if not is_tuple:
3619 /// 0. captures_len: u32 // if `any_captures`
3620 /// 1. capture: CaptureValue // for each `captures_len`
3621 /// 2. type: Index for each field in declared order
3622 /// 3. if not is_tuple:
34973623 /// names_map: MapIndex,
34983624 /// name: NullTerminatedString // for each field in declared order
3499 /// 2. if any_default_inits:
3625 /// 4. if any_default_inits:
35003626 /// init: Index // for each field in declared order
3501 /// 3. if has_namespace:
3627 /// 5. if has_namespace:
35023628 /// namespace: NamespaceIndex
3503 /// 4. if any_aligned_fields:
3629 /// 6. if any_aligned_fields:
35043630 /// align: Alignment // for each field in declared order
3505 /// 5. if any_comptime_fields:
3631 /// 7. if any_comptime_fields:
35063632 /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0
3507 /// 6. if not is_extern:
3633 /// 8. if not is_extern:
35083634 /// field_index: RuntimeOrder // for each field in runtime order
3509 /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved
3635 /// 9. field_offset: u32 // for each field in declared order, undef until layout_resolved
35103636 pub const TypeStruct = struct {
35113637 decl: DeclIndex,
35123638 zir_index: TrackedInst.Index.Optional,
......@@ -3515,6 +3641,7 @@ pub const Tag = enum(u8) {
35153641 size: u32,
35163642
35173643 pub const Flags = packed struct(u32) {
3644 any_captures: bool,
35183645 is_extern: bool,
35193646 known_non_opv: bool,
35203647 requires_comptime: RequiresComptime,
......@@ -3544,9 +3671,21 @@ pub const Tag = enum(u8) {
35443671 // which `layout_resolved` does not ensure.
35453672 fully_resolved: bool,
35463673
3547 _: u8 = 0,
3674 _: u7 = 0,
35483675 };
35493676 };
3677
3678 /// Trailing:
3679 /// 0. capture: CaptureValue // for each `captures_len`
3680 pub const TypeOpaque = struct {
3681 /// The opaque's owner Decl.
3682 decl: DeclIndex,
3683 /// Contains the declarations inside this opaque.
3684 namespace: NamespaceIndex,
3685 /// The index of the `opaque_decl` instruction.
3686 zir_index: TrackedInst.Index.Optional,
3687 captures_len: u32,
3688 };
35503689};
35513690
35523691/// State that is mutable during semantic analysis. This data is not used for
......@@ -3853,11 +3992,13 @@ pub const Array = struct {
38533992};
38543993
38553994/// Trailing:
3856/// 0. field name: NullTerminatedString for each fields_len; declaration order
3857/// 1. tag value: Index for each fields_len; declaration order
3995/// 0. capture: CaptureValue // for each `captures_len`
3996/// 1. field name: NullTerminatedString for each fields_len; declaration order
3997/// 2. tag value: Index for each fields_len; declaration order
38583998pub const EnumExplicit = struct {
38593999 /// The Decl that corresponds to the enum itself.
38604000 decl: DeclIndex,
4001 captures_len: u32,
38614002 /// This may be `none` if there are no declarations.
38624003 namespace: OptionalNamespaceIndex,
38634004 /// An integer type which is used for the numerical value of the enum, which
......@@ -3874,10 +4015,12 @@ pub const EnumExplicit = struct {
38744015};
38754016
38764017/// Trailing:
3877/// 0. field name: NullTerminatedString for each fields_len; declaration order
4018/// 0. capture: CaptureValue // for each `captures_len`
4019/// 1. field name: NullTerminatedString for each fields_len; declaration order
38784020pub const EnumAuto = struct {
38794021 /// The Decl that corresponds to the enum itself.
38804022 decl: DeclIndex,
4023 captures_len: u32,
38814024 /// This may be `none` if there are no declarations.
38824025 namespace: OptionalNamespaceIndex,
38834026 /// An integer type which is used for the numerical value of the enum, which
......@@ -4187,7 +4330,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
41874330 .inferred_error_set_type = @enumFromInt(data),
41884331 },
41894332
4190 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
4333 .type_opaque => .{ .opaque_type = .{
4334 .decl = ip.extraData(Tag.TypeOpaque, data).decl,
4335 } },
41914336
41924337 .type_struct => .{ .struct_type = if (data == 0) .{
41934338 .decl = .none,
......@@ -5497,7 +5642,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
54975642}
54985643
54995644pub const UnionTypeInit = struct {
5500 flags: Tag.TypeUnion.Flags,
5645 flags: packed struct {
5646 runtime_tag: LoadedUnionType.RuntimeTag,
5647 any_aligned_fields: bool,
5648 layout: std.builtin.Type.ContainerLayout,
5649 status: LoadedUnionType.Status,
5650 requires_comptime: RequiresComptime,
5651 assumed_runtime_bits: bool,
5652 assumed_pointer_aligned: bool,
5653 alignment: Alignment,
5654 },
55015655 decl: DeclIndex,
55025656 namespace: NamespaceIndex,
55035657 zir_index: TrackedInst.Index.Optional,
......@@ -5509,6 +5663,7 @@ pub const UnionTypeInit = struct {
55095663 /// The logic for `any_aligned_fields` is asserted to have been done before
55105664 /// calling this function.
55115665 field_aligns: []const Alignment,
5666 captures: []const CaptureValue,
55125667};
55135668
55145669pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocator.Error!Index {
......@@ -5516,12 +5671,24 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
55165671 const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0;
55175672 const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4);
55185673 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeUnion).Struct.fields.len +
5674 @intFromBool(ini.captures.len != 0) + // captures_len
5675 ini.captures.len + // captures
55195676 ini.fields_len + // field types
55205677 align_elements_len);
55215678 try ip.items.ensureUnusedCapacity(gpa, 1);
55225679
55235680 const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{
5524 .flags = ini.flags,
5681 .flags = .{
5682 .any_captures = ini.captures.len != 0,
5683 .runtime_tag = ini.flags.runtime_tag,
5684 .any_aligned_fields = ini.flags.any_aligned_fields,
5685 .layout = ini.flags.layout,
5686 .status = ini.flags.status,
5687 .requires_comptime = ini.flags.requires_comptime,
5688 .assumed_runtime_bits = ini.flags.assumed_runtime_bits,
5689 .assumed_pointer_aligned = ini.flags.assumed_pointer_aligned,
5690 .alignment = ini.flags.alignment,
5691 },
55255692 .fields_len = ini.fields_len,
55265693 .size = std.math.maxInt(u32),
55275694 .padding = std.math.maxInt(u32),
......@@ -5531,6 +5698,11 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
55315698 .zir_index = ini.zir_index,
55325699 });
55335700
5701 if (ini.captures.len != 0) {
5702 ip.extra.appendAssumeCapacity(@intCast(ini.captures.len));
5703 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
5704 }
5705
55345706 // field types
55355707 if (ini.field_types.len > 0) {
55365708 assert(ini.field_types.len == ini.fields_len);
......@@ -5582,6 +5754,7 @@ pub const StructTypeInit = struct {
55825754 any_default_inits: bool,
55835755 inits_resolved: bool,
55845756 any_aligned_fields: bool,
5757 captures: []const CaptureValue,
55855758};
55865759
55875760pub fn getStructType(
......@@ -5605,6 +5778,8 @@ pub fn getStructType(
56055778 .Extern => true,
56065779 .Packed => {
56075780 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStructPacked).Struct.fields.len +
5781 @intFromBool(ini.captures.len != 0) + // captures_len
5782 ini.captures.len + // captures
56085783 ini.fields_len + // types
56095784 ini.fields_len + // names
56105785 ini.fields_len); // inits
......@@ -5618,11 +5793,16 @@ pub fn getStructType(
56185793 .backing_int_ty = .none,
56195794 .names_map = names_map,
56205795 .flags = .{
5796 .any_captures = ini.captures.len != 0,
56215797 .field_inits_wip = false,
56225798 .inits_resolved = ini.inits_resolved,
56235799 },
56245800 }),
56255801 });
5802 if (ini.captures.len != 0) {
5803 ip.extra.appendAssumeCapacity(@intCast(ini.captures.len));
5804 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
5805 }
56265806 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len);
56275807 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(OptionalNullTerminatedString.none), ini.fields_len);
56285808 if (ini.any_default_inits) {
......@@ -5637,6 +5817,8 @@ pub fn getStructType(
56375817 const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0;
56385818
56395819 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStruct).Struct.fields.len +
5820 @intFromBool(ini.captures.len != 0) + // captures_len
5821 ini.captures.len + // captures
56405822 (ini.fields_len * 5) + // types, names, inits, runtime order, offsets
56415823 align_elements_len + comptime_elements_len +
56425824 2); // names_map + namespace
......@@ -5648,6 +5830,7 @@ pub fn getStructType(
56485830 .fields_len = ini.fields_len,
56495831 .size = std.math.maxInt(u32),
56505832 .flags = .{
5833 .any_captures = ini.captures.len != 0,
56515834 .is_extern = is_extern,
56525835 .known_non_opv = ini.known_non_opv,
56535836 .requires_comptime = ini.requires_comptime,
......@@ -5669,6 +5852,10 @@ pub fn getStructType(
56695852 },
56705853 }),
56715854 });
5855 if (ini.captures.len != 0) {
5856 ip.extra.appendAssumeCapacity(@intCast(ini.captures.len));
5857 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
5858 }
56725859 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len);
56735860 if (!ini.is_tuple) {
56745861 ip.extra.appendAssumeCapacity(@intFromEnum(names_map));
......@@ -6405,11 +6592,12 @@ fn getIncompleteEnumAuto(
64056592 const names_map = try ip.addMap(gpa, enum_type.fields_len);
64066593
64076594 const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len;
6408 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len);
6595 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.captures.len + enum_type.fields_len);
64096596 try ip.items.ensureUnusedCapacity(gpa, 1);
64106597
64116598 const extra_index = ip.addExtraAssumeCapacity(EnumAuto{
64126599 .decl = enum_type.decl,
6600 .captures_len = @intCast(enum_type.captures.len),
64136601 .namespace = enum_type.namespace,
64146602 .int_tag_type = int_tag_type,
64156603 .names_map = names_map,
......@@ -6421,6 +6609,7 @@ fn getIncompleteEnumAuto(
64216609 .tag = .type_enum_auto,
64226610 .data = extra_index,
64236611 });
6612 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.captures));
64246613 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), enum_type.fields_len);
64256614 return .{
64266615 .index = @enumFromInt(ip.items.len - 1),
......@@ -6455,11 +6644,12 @@ fn getIncompleteEnumExplicit(
64556644 if (enum_type.has_values) enum_type.fields_len else 0;
64566645
64576646 const extra_fields_len: u32 = @typeInfo(EnumExplicit).Struct.fields.len;
6458 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + reserved_len);
6647 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.captures.len + reserved_len);
64596648 try ip.items.ensureUnusedCapacity(gpa, 1);
64606649
64616650 const extra_index = ip.addExtraAssumeCapacity(EnumExplicit{
64626651 .decl = enum_type.decl,
6652 .captures_len = @intCast(enum_type.captures.len),
64636653 .namespace = enum_type.namespace,
64646654 .int_tag_type = enum_type.tag_ty,
64656655 .fields_len = enum_type.fields_len,
......@@ -6472,6 +6662,7 @@ fn getIncompleteEnumExplicit(
64726662 .tag = tag,
64736663 .data = extra_index,
64746664 });
6665 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.captures));
64756666 // This is both fields and values (if present).
64766667 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), reserved_len);
64776668 return .{
......@@ -6492,6 +6683,7 @@ pub const GetEnumInit = struct {
64926683 values: []const Index,
64936684 tag_mode: LoadedEnumType.TagMode,
64946685 zir_index: TrackedInst.Index.Optional,
6686 captures: []const CaptureValue,
64956687};
64966688
64976689pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {
......@@ -6513,11 +6705,12 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro
65136705
65146706 const fields_len: u32 = @intCast(ini.names.len);
65156707 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
6516 fields_len);
6708 ini.captures.len + fields_len);
65176709 ip.items.appendAssumeCapacity(.{
65186710 .tag = .type_enum_auto,
65196711 .data = ip.addExtraAssumeCapacity(EnumAuto{
65206712 .decl = ini.decl,
6713 .captures_len = @intCast(ini.captures.len),
65216714 .namespace = ini.namespace,
65226715 .int_tag_type = ini.tag_ty,
65236716 .names_map = names_map,
......@@ -6525,6 +6718,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro
65256718 .zir_index = ini.zir_index,
65266719 }),
65276720 });
6721 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
65286722 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
65296723 return @enumFromInt(ip.items.len - 1);
65306724 },
......@@ -6533,7 +6727,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro
65336727 }
65346728}
65356729
6536pub fn finishGetEnum(
6730fn finishGetEnum(
65376731 ip: *InternPool,
65386732 gpa: Allocator,
65396733 ini: GetEnumInit,
......@@ -6549,11 +6743,12 @@ pub fn finishGetEnum(
65496743 };
65506744 const fields_len: u32 = @intCast(ini.names.len);
65516745 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +
6552 fields_len);
6746 ini.captures.len + fields_len);
65536747 ip.items.appendAssumeCapacity(.{
65546748 .tag = tag,
65556749 .data = ip.addExtraAssumeCapacity(EnumExplicit{
65566750 .decl = ini.decl,
6751 .captures_len = @intCast(ini.captures.len),
65576752 .namespace = ini.namespace,
65586753 .int_tag_type = ini.tag_ty,
65596754 .fields_len = fields_len,
......@@ -6562,23 +6757,37 @@ pub fn finishGetEnum(
65626757 .zir_index = ini.zir_index,
65636758 }),
65646759 });
6760 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
65656761 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
65666762 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values));
65676763 return @enumFromInt(ip.items.len - 1);
65686764}
65696765
6570pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, key: LoadedOpaqueType) Allocator.Error!Index {
6766pub const OpaqueTypeIni = struct {
6767 decl: DeclIndex,
6768 namespace: NamespaceIndex,
6769 zir_index: TrackedInst.Index.Optional,
6770 captures: []const CaptureValue,
6771};
6772
6773pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, ini: OpaqueTypeIni) Allocator.Error!Index {
65716774 const adapter: KeyAdapter = .{ .intern_pool = ip };
6572 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(LoadedOpaqueType).Struct.fields.len);
6775 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(LoadedOpaqueType).Struct.fields.len + ini.captures.len);
65736776 try ip.items.ensureUnusedCapacity(gpa, 1);
65746777 const gop = try ip.map.getOrPutAdapted(gpa, Key{
6575 .opaque_type = .{ .decl = key.decl },
6778 .opaque_type = .{ .decl = ini.decl },
65766779 }, adapter);
65776780 if (gop.found_existing) return @enumFromInt(gop.index);
65786781 ip.items.appendAssumeCapacity(.{
65796782 .tag = .type_opaque,
6580 .data = ip.addExtraAssumeCapacity(key),
6783 .data = ip.addExtraAssumeCapacity(Tag.TypeOpaque{
6784 .decl = ini.decl,
6785 .namespace = ini.namespace,
6786 .zir_index = ini.zir_index,
6787 .captures_len = @intCast(ini.captures.len),
6788 }),
65816789 });
6790 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
65826791 return @enumFromInt(gop.index);
65836792}
65846793
......@@ -7442,12 +7651,31 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
74427651 break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
74437652 },
74447653 .type_inferred_error_set => 0,
7445 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
7446 .type_enum_auto => @sizeOf(EnumAuto),
7447 .type_opaque => @sizeOf(Key.OpaqueType),
7654 .type_enum_explicit, .type_enum_nonexhaustive => b: {
7655 const info = ip.extraData(EnumExplicit, data);
7656 var ints = @typeInfo(EnumExplicit).Struct.fields.len + info.captures_len + info.fields_len;
7657 if (info.values_map != .none) ints += info.fields_len;
7658 break :b @sizeOf(u32) * ints;
7659 },
7660 .type_enum_auto => b: {
7661 const info = ip.extraData(EnumAuto, data);
7662 const ints = @typeInfo(EnumAuto).Struct.fields.len + info.captures_len + info.fields_len;
7663 break :b @sizeOf(u32) * ints;
7664 },
7665 .type_opaque => b: {
7666 const info = ip.extraData(Tag.TypeOpaque, data);
7667 const ints = @typeInfo(Tag.TypeOpaque).Struct.fields.len + info.captures_len;
7668 break :b @sizeOf(u32) * ints;
7669 },
74487670 .type_struct => b: {
7449 const info = ip.extraData(Tag.TypeStruct, data);
7671 if (data == 0) break :b 0;
7672 const extra = ip.extraDataTrail(Tag.TypeStruct, data);
7673 const info = extra.data;
74507674 var ints: usize = @typeInfo(Tag.TypeStruct).Struct.fields.len;
7675 if (info.flags.any_captures) {
7676 const captures_len = ip.extra.items[extra.end];
7677 ints += 1 + captures_len;
7678 }
74517679 ints += info.fields_len; // types
74527680 if (!info.flags.is_tuple) {
74537681 ints += 1; // names_map
......@@ -7470,14 +7698,24 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
74707698 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
74717699 },
74727700 .type_struct_packed => b: {
7473 const info = ip.extraData(Tag.TypeStructPacked, data);
7701 const extra = ip.extraDataTrail(Tag.TypeStructPacked, data);
7702 const captures_len = if (extra.data.flags.any_captures)
7703 ip.extra.items[extra.end]
7704 else
7705 0;
74747706 break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len +
7475 info.fields_len + info.fields_len);
7707 @intFromBool(extra.data.flags.any_captures) + captures_len +
7708 extra.data.fields_len * 2);
74767709 },
74777710 .type_struct_packed_inits => b: {
7478 const info = ip.extraData(Tag.TypeStructPacked, data);
7711 const extra = ip.extraDataTrail(Tag.TypeStructPacked, data);
7712 const captures_len = if (extra.data.flags.any_captures)
7713 ip.extra.items[extra.end]
7714 else
7715 0;
74797716 break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len +
7480 info.fields_len + info.fields_len + info.fields_len);
7717 @intFromBool(extra.data.flags.any_captures) + captures_len +
7718 extra.data.fields_len * 3);
74817719 },
74827720 .type_tuple_anon => b: {
74837721 const info = ip.extraData(TypeStructAnon, data);
......@@ -7485,16 +7723,20 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
74857723 },
74867724
74877725 .type_union => b: {
7488 const info = ip.extraData(Tag.TypeUnion, data);
7489 const enum_info = ip.loadEnumType(info.tag_ty);
7490 const fields_len: u32 = @intCast(enum_info.names.len);
7726 const extra = ip.extraDataTrail(Tag.TypeUnion, data);
7727 const captures_len = if (extra.data.flags.any_captures)
7728 ip.extra.items[extra.end]
7729 else
7730 0;
74917731 const per_field = @sizeOf(u32); // field type
74927732 // 1 byte per field for alignment, rounded up to the nearest 4 bytes
7493 const alignments = if (info.flags.any_aligned_fields)
7494 ((fields_len + 3) / 4) * 4
7733 const alignments = if (extra.data.flags.any_aligned_fields)
7734 ((extra.data.fields_len + 3) / 4) * 4
74957735 else
74967736 0;
7497 break :b @sizeOf(Tag.TypeUnion) + (fields_len * per_field) + alignments;
7737 break :b @sizeOf(Tag.TypeUnion) +
7738 4 * (@intFromBool(extra.data.flags.any_captures) + captures_len) +
7739 (extra.data.fields_len * per_field) + alignments;
74987740 },
74997741
75007742 .type_function => b: {
......@@ -7802,7 +8044,6 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex)
78028044 .parent = undefined,
78038045 .file_scope = undefined,
78048046 .decl_index = undefined,
7805 .captures = undefined,
78068047 };
78078048 ip.namespaces_free_list.append(gpa, index) catch {
78088049 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory
src/Module.zig-33
......@@ -761,37 +761,6 @@ pub const Namespace = struct {
761761 /// the Decl Value has to be resolved as a Type which has a Namespace.
762762 /// Value is whether the usingnamespace decl is marked `pub`.
763763 usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},
764 /// Allocated into `gpa`.
765 /// The ordered set of values captured in this type's closure.
766 /// `closure_get` instructions look up values in this list.
767 captures: []CaptureValue,
768
769 /// A single value captured in a container's closure. This is not an
770 /// `InternPool.Index` so we can differentiate between runtime-known values
771 /// (where only the type is comptime-known) and comptime-known values.
772 pub const CaptureValue = enum(u32) {
773 _,
774 pub const Unwrapped = union(enum) {
775 /// Index refers to the value.
776 @"comptime": InternPool.Index,
777 /// Index refers to the type.
778 runtime: InternPool.Index,
779 };
780 pub fn wrap(val: Unwrapped) CaptureValue {
781 return switch (val) {
782 .@"comptime" => |i| @enumFromInt(@intFromEnum(i)),
783 .runtime => |i| @enumFromInt((1 << 31) | @intFromEnum(i)),
784 };
785 }
786 pub fn unwrap(val: CaptureValue) Unwrapped {
787 const tag: u1 = @intCast(@intFromEnum(val) >> 31);
788 const raw = @intFromEnum(val);
789 return switch (tag) {
790 0 => .{ .@"comptime" = @enumFromInt(raw) },
791 1 => .{ .runtime = @enumFromInt(@as(u31, @truncate(raw))) },
792 };
793 }
794 };
795764
796765 const Index = InternPool.NamespaceIndex;
797766 const OptionalIndex = InternPool.OptionalNamespaceIndex;
......@@ -2130,7 +2099,6 @@ pub fn deinit(zcu: *Zcu) void {
21302099 while (it.next()) |namespace| {
21312100 namespace.decls.deinit(gpa);
21322101 namespace.usingnamespace_set.deinit(gpa);
2133 gpa.free(namespace.captures);
21342102 }
21352103 }
21362104
......@@ -3354,7 +3322,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
33543322 .parent = .none,
33553323 .decl_index = undefined,
33563324 .file_scope = file,
3357 .captures = &.{},
33583325 });
33593326 const new_namespace = mod.namespacePtr(new_namespace_index);
33603327 errdefer mod.destroyNamespace(new_namespace_index);
src/Sema.zig+24-20
......@@ -2670,28 +2670,27 @@ fn analyzeAsInt(
26702670}
26712671
26722672/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
2673/// resolves this into a list of `Namespace.CaptureValue` allocated by `gpa`.
2674/// Caller owns returned memory.
2675fn getCaptures(sema: *Sema, parent_namespace: ?InternPool.NamespaceIndex, extra_index: usize, captures_len: u32) ![]Namespace.CaptureValue {
2676 const gpa = sema.gpa;
2677 const parent_captures: []const Namespace.CaptureValue = if (parent_namespace) |p| parent: {
2678 break :parent sema.mod.namespacePtr(p).captures;
2679 } else &.{};
2673/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.
2674fn getCaptures(sema: *Sema, parent_namespace: ?InternPool.NamespaceIndex, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
2675 const zcu = sema.mod;
2676 const ip = &zcu.intern_pool;
2677 const parent_captures: InternPool.CaptureValue.Slice = if (parent_namespace) |p| parent: {
2678 break :parent zcu.namespacePtr(p).ty.getCaptures(zcu);
2679 } else undefined; // never used so `undefined` is safe
26802680
2681 const captures = try gpa.alloc(Namespace.CaptureValue, captures_len);
2682 errdefer gpa.free(captures);
2681 const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len);
26832682
26842683 for (sema.code.extra[extra_index..][0..captures_len], captures) |raw, *capture| {
26852684 const zir_capture: Zir.Inst.Capture = @enumFromInt(raw);
26862685 capture.* = switch (zir_capture.unwrap()) {
2687 .inst => |inst| Namespace.CaptureValue.wrap(capture: {
2686 .inst => |inst| InternPool.CaptureValue.wrap(capture: {
26882687 const air_ref = try sema.resolveInst(inst.toRef());
26892688 if (try sema.resolveValue(air_ref)) |val| {
26902689 break :capture .{ .@"comptime" = val.toIntern() };
26912690 }
26922691 break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() };
26932692 }),
2694 .nested => |parent_idx| parent_captures[parent_idx],
2693 .nested => |parent_idx| parent_captures.get(ip)[parent_idx],
26952694 };
26962695 }
26972696
......@@ -2731,7 +2730,7 @@ pub fn getStructType(
27312730 break :blk decls_len;
27322731 } else 0;
27332732
2734 mod.namespacePtr(namespace).captures = try sema.getCaptures(parent_namespace, extra_index, captures_len);
2733 const captures = try sema.getCaptures(parent_namespace, extra_index, captures_len);
27352734 extra_index += captures_len;
27362735
27372736 if (small.has_backing_int) {
......@@ -2761,6 +2760,7 @@ pub fn getStructType(
27612760 .any_comptime_fields = small.any_comptime_fields,
27622761 .inits_resolved = false,
27632762 .any_aligned_fields = small.any_aligned_fields,
2763 .captures = captures,
27642764 });
27652765
27662766 return ty;
......@@ -2801,7 +2801,6 @@ fn zirStructDecl(
28012801 .parent = block.namespace.toOptional(),
28022802 .decl_index = new_decl_index,
28032803 .file_scope = block.getFileScope(mod),
2804 .captures = &.{}, // Will be set by `getStructType`
28052804 });
28062805 errdefer mod.destroyNamespace(new_namespace_index);
28072806
......@@ -2997,7 +2996,6 @@ fn zirEnumDecl(
29972996 .parent = block.namespace.toOptional(),
29982997 .decl_index = new_decl_index,
29992998 .file_scope = block.getFileScope(mod),
3000 .captures = captures,
30012999 });
30023000 errdefer if (!done) mod.destroyNamespace(new_namespace_index);
30033001
......@@ -3029,6 +3027,7 @@ fn zirEnumDecl(
30293027 else
30303028 .explicit,
30313029 .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),
3030 .captures = captures,
30323031 });
30333032 if (sema.builtin_type_target_index != .none) {
30343033 mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index);
......@@ -3261,7 +3260,6 @@ fn zirUnionDecl(
32613260 .parent = block.namespace.toOptional(),
32623261 .decl_index = new_decl_index,
32633262 .file_scope = block.getFileScope(mod),
3264 .captures = captures,
32653263 });
32663264 errdefer mod.destroyNamespace(new_namespace_index);
32673265
......@@ -3291,6 +3289,7 @@ fn zirUnionDecl(
32913289 .enum_tag_ty = .none,
32923290 .field_types = &.{},
32933291 .field_aligns = &.{},
3292 .captures = captures,
32943293 });
32953294 if (sema.builtin_type_target_index != .none) {
32963295 mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, ty);
......@@ -3367,7 +3366,6 @@ fn zirOpaqueDecl(
33673366 .parent = block.namespace.toOptional(),
33683367 .decl_index = new_decl_index,
33693368 .file_scope = block.getFileScope(mod),
3370 .captures = captures,
33713369 });
33723370 errdefer mod.destroyNamespace(new_namespace_index);
33733371
......@@ -3375,6 +3373,7 @@ fn zirOpaqueDecl(
33753373 .decl = new_decl_index,
33763374 .namespace = new_namespace_index,
33773375 .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),
3376 .captures = captures,
33783377 });
33793378 // TODO: figure out InternPool removals for incremental compilation
33803379 //errdefer mod.intern_pool.remove(opaque_ty);
......@@ -17287,12 +17286,13 @@ fn zirThis(
1728717286
1728817287fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
1728917288 const mod = sema.mod;
17290 const captures = mod.namespacePtr(block.namespace).captures;
17289 const ip = &mod.intern_pool;
17290 const captures = mod.namespacePtr(block.namespace).ty.getCaptures(mod);
1729117291
1729217292 const src_node: i32 = @bitCast(extended.operand);
1729317293 const src = LazySrcLoc.nodeOffset(src_node);
1729417294
17295 const capture_ty = switch (captures[extended.small].unwrap()) {
17295 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {
1729617296 .@"comptime" => |index| return Air.internedToRef(index),
1729717297 .runtime => |index| index,
1729817298 };
......@@ -21360,6 +21360,7 @@ fn zirReify(
2136021360 .explicit,
2136121361 .tag_ty = int_tag_ty.toIntern(),
2136221362 .zir_index = .none,
21363 .captures = &.{},
2136321364 });
2136421365 // TODO: figure out InternPool removals for incremental compilation
2136521366 //errdefer ip.remove(incomplete_enum.index);
......@@ -21450,7 +21451,6 @@ fn zirReify(
2145021451 .parent = block.namespace.toOptional(),
2145121452 .decl_index = new_decl_index,
2145221453 .file_scope = block.getFileScope(mod),
21453 .captures = &.{},
2145421454 });
2145521455 errdefer mod.destroyNamespace(new_namespace_index);
2145621456
......@@ -21458,6 +21458,7 @@ fn zirReify(
2145821458 .decl = new_decl_index,
2145921459 .namespace = new_namespace_index,
2146021460 .zir_index = .none,
21461 .captures = &.{},
2146121462 });
2146221463 // TODO: figure out InternPool removals for incremental compilation
2146321464 //errdefer ip.remove(opaque_ty);
......@@ -21659,7 +21660,6 @@ fn zirReify(
2165921660 .parent = block.namespace.toOptional(),
2166021661 .decl_index = new_decl_index,
2166121662 .file_scope = block.getFileScope(mod),
21662 .captures = &.{},
2166321663 });
2166421664 errdefer mod.destroyNamespace(new_namespace_index);
2166521665
......@@ -21688,6 +21688,7 @@ fn zirReify(
2168821688 },
2168921689 .field_types = union_fields.items(.type),
2169021690 .field_aligns = if (any_aligned_fields) union_fields.items(.alignment) else &.{},
21691 .captures = &.{},
2169121692 });
2169221693
2169321694 new_decl.ty = Type.type;
......@@ -21849,6 +21850,7 @@ fn reifyStruct(
2184921850 .any_default_inits = true,
2185021851 .inits_resolved = true,
2185121852 .any_aligned_fields = true,
21853 .captures = &.{},
2185221854 });
2185321855 // TODO: figure out InternPool removals for incremental compilation
2185421856 //errdefer ip.remove(ty);
......@@ -37404,6 +37406,7 @@ fn generateUnionTagTypeNumbered(
3740437406 .values = enum_field_vals,
3740537407 .tag_mode = .explicit,
3740637408 .zir_index = .none,
37409 .captures = &.{},
3740737410 });
3740837411
3740937412 new_decl.ty = Type.type;
......@@ -37455,6 +37458,7 @@ fn generateUnionTagTypeSimple(
3745537458 .values = &.{},
3745637459 .tag_mode = .auto,
3745737460 .zir_index = .none,
37461 .captures = &.{},
3745837462 });
3745937463
3746037464 const new_decl = mod.declPtr(new_decl_index);
src/type.zig+12
......@@ -3294,6 +3294,18 @@ pub const Type = struct {
32943294 };
32953295 }
32963296
3297 /// Given a namespace type, returns its list of caotured values.
3298 pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice {
3299 const ip = &zcu.intern_pool;
3300 return switch (ip.indexToKey(ty.toIntern())) {
3301 .struct_type => ip.loadStructType(ty.toIntern()).captures,
3302 .union_type => ip.loadUnionType(ty.toIntern()).captures,
3303 .enum_type => ip.loadEnumType(ty.toIntern()).captures,
3304 .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures,
3305 else => unreachable,
3306 };
3307 }
3308
32973309 pub const @"u1": Type = .{ .ip_index = .u1_type };
32983310 pub const @"u8": Type = .{ .ip_index = .u8_type };
32993311 pub const @"u16": Type = .{ .ip_index = .u16_type };