authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-09 19:50:52-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 11:10:49-04:00
log3aa48bf859b3eba17c0431c15ae79ab303219eff
tree36c49c7247af655fa2281a848e7aa1ef5d7e01cf
parent9cf42b103601c26294739143f6aeb4b93e1858d8

InternPool: fix race on struct flags


1 files changed, 95 insertions(+), 80 deletions(-)

src/InternPool.zig+95-80
...@@ -2783,20 +2783,22 @@ pub const LoadedStructType = struct {...@@ -2783,20 +2783,22 @@ pub const LoadedStructType = struct {
2783 }2783 }
27842784
2785 pub fn setInitsWip(s: LoadedStructType, ip: *InternPool) bool {2785 pub fn setInitsWip(s: LoadedStructType, ip: *InternPool) bool {
2786 switch (s.layout) {2786 return switch (s.layout) {
2787 .@"packed" => {2787 .@"packed" => @as(Tag.TypeStructPacked.Flags, @bitCast(@atomicRmw(
2788 const flag = &s.packedFlagsPtr(ip).field_inits_wip;2788 u32,
2789 if (flag.*) return true;2789 @as(*u32, @ptrCast(s.packedFlagsPtr(ip))),
2790 flag.* = true;2790 .Or,
2791 return false;2791 @bitCast(Tag.TypeStructPacked.Flags{ .field_inits_wip = true }),
2792 },2792 .acq_rel,
2793 .auto, .@"extern" => {2793 ))).field_inits_wip,
2794 const flag = &s.flagsPtr(ip).field_inits_wip;2794 .auto, .@"extern" => @as(Tag.TypeStruct.Flags, @bitCast(@atomicRmw(
2795 if (flag.*) return true;2795 u32,
2796 flag.* = true;2796 @as(*u32, @ptrCast(s.flagsPtr(ip))),
2797 return false;2797 .Or,
2798 },2798 @bitCast(Tag.TypeStruct.Flags{ .field_inits_wip = true }),
2799 }2799 .acq_rel,
2800 ))).field_inits_wip,
2801 };
2800 }2802 }
28012803
2802 pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool) void {2804 pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool) void {
...@@ -2962,6 +2964,7 @@ pub const LoadedStructType = struct {...@@ -2962,6 +2964,7 @@ pub const LoadedStructType = struct {
2962pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {2964pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
2963 const unwrapped_index = index.unwrap(ip);2965 const unwrapped_index = index.unwrap(ip);
2964 const extra_list = unwrapped_index.getExtra(ip);2966 const extra_list = unwrapped_index.getExtra(ip);
2967 const extra_items = extra_list.view().items(.@"0");
2965 const item = unwrapped_index.getItem(ip);2968 const item = unwrapped_index.getItem(ip);
2966 switch (item.tag) {2969 switch (item.tag) {
2967 .type_struct => {2970 .type_struct => {
...@@ -2982,10 +2985,12 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -2982,10 +2985,12 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
2982 .names_map = .none,2985 .names_map = .none,
2983 .captures = CaptureValue.Slice.empty,2986 .captures = CaptureValue.Slice.empty,
2984 };2987 };
2985 const extra = extraDataTrail(extra_list, Tag.TypeStruct, item.data);2988 const decl: DeclIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "decl").?]);
2986 const fields_len = extra.data.fields_len;2989 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
2987 var extra_index = extra.end;2990 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];
2988 const captures_len = if (extra.data.flags.any_captures) c: {2991 const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .monotonic));
2992 var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStruct).Struct.fields.len);
2993 const captures_len = if (flags.any_captures) c: {
2989 const len = extra_list.view().items(.@"0")[extra_index];2994 const len = extra_list.view().items(.@"0")[extra_index];
2990 extra_index += 1;2995 extra_index += 1;
2991 break :c len;2996 break :c len;
...@@ -2996,7 +3001,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -2996,7 +3001,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
2996 .len = captures_len,3001 .len = captures_len,
2997 };3002 };
2998 extra_index += captures_len;3003 extra_index += captures_len;
2999 if (extra.data.flags.is_reified) {3004 if (flags.is_reified) {
3000 extra_index += 2; // PackedU643005 extra_index += 2; // PackedU64
3001 }3006 }
3002 const field_types: Index.Slice = .{3007 const field_types: Index.Slice = .{
...@@ -3005,7 +3010,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3005,7 +3010,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3005 .len = fields_len,3010 .len = fields_len,
3006 };3011 };
3007 extra_index += fields_len;3012 extra_index += fields_len;
3008 const names_map: OptionalMapIndex, const names = if (!extra.data.flags.is_tuple) n: {3013 const names_map: OptionalMapIndex, const names = if (!flags.is_tuple) n: {
3009 const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);3014 const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
3010 extra_index += 1;3015 extra_index += 1;
3011 const names: NullTerminatedString.Slice = .{3016 const names: NullTerminatedString.Slice = .{
...@@ -3016,7 +3021,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3016,7 +3021,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3016 extra_index += fields_len;3021 extra_index += fields_len;
3017 break :n .{ names_map, names };3022 break :n .{ names_map, names };
3018 } else .{ .none, NullTerminatedString.Slice.empty };3023 } else .{ .none, NullTerminatedString.Slice.empty };
3019 const inits: Index.Slice = if (extra.data.flags.any_default_inits) i: {3024 const inits: Index.Slice = if (flags.any_default_inits) i: {
3020 const inits: Index.Slice = .{3025 const inits: Index.Slice = .{
3021 .tid = unwrapped_index.tid,3026 .tid = unwrapped_index.tid,
3022 .start = extra_index,3027 .start = extra_index,
...@@ -3025,12 +3030,12 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3025,12 +3030,12 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3025 extra_index += fields_len;3030 extra_index += fields_len;
3026 break :i inits;3031 break :i inits;
3027 } else Index.Slice.empty;3032 } else Index.Slice.empty;
3028 const namespace: OptionalNamespaceIndex = if (extra.data.flags.has_namespace) n: {3033 const namespace: OptionalNamespaceIndex = if (flags.has_namespace) n: {
3029 const n: NamespaceIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);3034 const n: NamespaceIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
3030 extra_index += 1;3035 extra_index += 1;
3031 break :n n.toOptional();3036 break :n n.toOptional();
3032 } else .none;3037 } else .none;
3033 const aligns: Alignment.Slice = if (extra.data.flags.any_aligned_fields) a: {3038 const aligns: Alignment.Slice = if (flags.any_aligned_fields) a: {
3034 const a: Alignment.Slice = .{3039 const a: Alignment.Slice = .{
3035 .tid = unwrapped_index.tid,3040 .tid = unwrapped_index.tid,
3036 .start = extra_index,3041 .start = extra_index,
...@@ -3039,7 +3044,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3039,7 +3044,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3039 extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;3044 extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;
3040 break :a a;3045 break :a a;
3041 } else Alignment.Slice.empty;3046 } else Alignment.Slice.empty;
3042 const comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) c: {3047 const comptime_bits: LoadedStructType.ComptimeBits = if (flags.any_comptime_fields) c: {
3043 const len = std.math.divCeil(u32, fields_len, 32) catch unreachable;3048 const len = std.math.divCeil(u32, fields_len, 32) catch unreachable;
3044 const c: LoadedStructType.ComptimeBits = .{3049 const c: LoadedStructType.ComptimeBits = .{
3045 .tid = unwrapped_index.tid,3050 .tid = unwrapped_index.tid,
...@@ -3049,7 +3054,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3049,7 +3054,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3049 extra_index += len;3054 extra_index += len;
3050 break :c c;3055 break :c c;
3051 } else LoadedStructType.ComptimeBits.empty;3056 } else LoadedStructType.ComptimeBits.empty;
3052 const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!extra.data.flags.is_extern) ro: {3057 const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!flags.is_extern) ro: {
3053 const ro: LoadedStructType.RuntimeOrder.Slice = .{3058 const ro: LoadedStructType.RuntimeOrder.Slice = .{
3054 .tid = unwrapped_index.tid,3059 .tid = unwrapped_index.tid,
3055 .start = extra_index,3060 .start = extra_index,
...@@ -3070,10 +3075,10 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3070,10 +3075,10 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3070 return .{3075 return .{
3071 .tid = unwrapped_index.tid,3076 .tid = unwrapped_index.tid,
3072 .extra_index = item.data,3077 .extra_index = item.data,
3073 .decl = extra.data.decl.toOptional(),3078 .decl = decl.toOptional(),
3074 .namespace = namespace,3079 .namespace = namespace,
3075 .zir_index = extra.data.zir_index.toOptional(),3080 .zir_index = zir_index.toOptional(),
3076 .layout = if (extra.data.flags.is_extern) .@"extern" else .auto,3081 .layout = if (flags.is_extern) .@"extern" else .auto,
3077 .field_names = names,3082 .field_names = names,
3078 .field_types = field_types,3083 .field_types = field_types,
3079 .field_inits = inits,3084 .field_inits = inits,
...@@ -3086,11 +3091,15 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3086,11 +3091,15 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3086 };3091 };
3087 },3092 },
3088 .type_struct_packed, .type_struct_packed_inits => {3093 .type_struct_packed, .type_struct_packed_inits => {
3089 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, item.data);3094 const decl: DeclIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "decl").?]);
3095 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
3096 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
3097 const namespace: OptionalNamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);
3098 const names_map: MapIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "names_map").?]);
3099 const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .monotonic));
3100 var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStructPacked).Struct.fields.len);
3090 const has_inits = item.tag == .type_struct_packed_inits;3101 const has_inits = item.tag == .type_struct_packed_inits;
3091 const fields_len = extra.data.fields_len;3102 const captures_len = if (flags.any_captures) c: {
3092 var extra_index = extra.end;
3093 const captures_len = if (extra.data.flags.any_captures) c: {
3094 const len = extra_list.view().items(.@"0")[extra_index];3103 const len = extra_list.view().items(.@"0")[extra_index];
3095 extra_index += 1;3104 extra_index += 1;
3096 break :c len;3105 break :c len;
...@@ -3101,7 +3110,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3101,7 +3110,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3101 .len = captures_len,3110 .len = captures_len,
3102 };3111 };
3103 extra_index += captures_len;3112 extra_index += captures_len;
3104 if (extra.data.flags.is_reified) {3113 if (flags.is_reified) {
3105 extra_index += 2; // PackedU643114 extra_index += 2; // PackedU64
3106 }3115 }
3107 const field_types: Index.Slice = .{3116 const field_types: Index.Slice = .{
...@@ -3128,9 +3137,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3128,9 +3137,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3128 return .{3137 return .{
3129 .tid = unwrapped_index.tid,3138 .tid = unwrapped_index.tid,
3130 .extra_index = item.data,3139 .extra_index = item.data,
3131 .decl = extra.data.decl.toOptional(),3140 .decl = decl.toOptional(),
3132 .namespace = extra.data.namespace,3141 .namespace = namespace,
3133 .zir_index = extra.data.zir_index.toOptional(),3142 .zir_index = zir_index.toOptional(),
3134 .layout = .@"packed",3143 .layout = .@"packed",
3135 .field_names = field_names,3144 .field_names = field_names,
3136 .field_types = field_types,3145 .field_types = field_types,
...@@ -3139,7 +3148,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3139,7 +3148,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3139 .runtime_order = LoadedStructType.RuntimeOrder.Slice.empty,3148 .runtime_order = LoadedStructType.RuntimeOrder.Slice.empty,
3140 .comptime_bits = LoadedStructType.ComptimeBits.empty,3149 .comptime_bits = LoadedStructType.ComptimeBits.empty,
3141 .offsets = LoadedStructType.Offsets.empty,3150 .offsets = LoadedStructType.Offsets.empty,
3142 .names_map = extra.data.names_map.toOptional(),3151 .names_map = names_map.toOptional(),
3143 .captures = captures,3152 .captures = captures,
3144 };3153 };
3145 },3154 },
...@@ -4476,11 +4485,11 @@ pub const Tag = enum(u8) {...@@ -4476,11 +4485,11 @@ pub const Tag = enum(u8) {
4476 flags: Flags,4485 flags: Flags,
44774486
4478 pub const Flags = packed struct(u32) {4487 pub const Flags = packed struct(u32) {
4479 any_captures: bool,4488 any_captures: bool = false,
4480 /// Dependency loop detection when resolving field inits.4489 /// Dependency loop detection when resolving field inits.
4481 field_inits_wip: bool,4490 field_inits_wip: bool = false,
4482 inits_resolved: bool,4491 inits_resolved: bool = false,
4483 is_reified: bool,4492 is_reified: bool = false,
4484 _: u28 = 0,4493 _: u28 = 0,
4485 };4494 };
4486 };4495 };
...@@ -4526,36 +4535,36 @@ pub const Tag = enum(u8) {...@@ -4526,36 +4535,36 @@ pub const Tag = enum(u8) {
4526 size: u32,4535 size: u32,
45274536
4528 pub const Flags = packed struct(u32) {4537 pub const Flags = packed struct(u32) {
4529 any_captures: bool,4538 any_captures: bool = false,
4530 is_extern: bool,4539 is_extern: bool = false,
4531 known_non_opv: bool,4540 known_non_opv: bool = false,
4532 requires_comptime: RequiresComptime,4541 requires_comptime: RequiresComptime = @enumFromInt(0),
4533 is_tuple: bool,4542 is_tuple: bool = false,
4534 assumed_runtime_bits: bool,4543 assumed_runtime_bits: bool = false,
4535 assumed_pointer_aligned: bool,4544 assumed_pointer_aligned: bool = false,
4536 has_namespace: bool,4545 has_namespace: bool = false,
4537 any_comptime_fields: bool,4546 any_comptime_fields: bool = false,
4538 any_default_inits: bool,4547 any_default_inits: bool = false,
4539 any_aligned_fields: bool,4548 any_aligned_fields: bool = false,
4540 /// `.none` until layout_resolved4549 /// `.none` until layout_resolved
4541 alignment: Alignment,4550 alignment: Alignment = @enumFromInt(0),
4542 /// Dependency loop detection when resolving struct alignment.4551 /// Dependency loop detection when resolving struct alignment.
4543 alignment_wip: bool,4552 alignment_wip: bool = false,
4544 /// Dependency loop detection when resolving field types.4553 /// Dependency loop detection when resolving field types.
4545 field_types_wip: bool,4554 field_types_wip: bool = false,
4546 /// Dependency loop detection when resolving struct layout.4555 /// Dependency loop detection when resolving struct layout.
4547 layout_wip: bool,4556 layout_wip: bool = false,
4548 /// Indicates whether `size`, `alignment`, runtime field order, and4557 /// Indicates whether `size`, `alignment`, runtime field order, and
4549 /// field offets are populated.4558 /// field offets are populated.
4550 layout_resolved: bool,4559 layout_resolved: bool = false,
4551 /// Dependency loop detection when resolving field inits.4560 /// Dependency loop detection when resolving field inits.
4552 field_inits_wip: bool,4561 field_inits_wip: bool = false,
4553 /// Indicates whether `field_inits` has been resolved.4562 /// Indicates whether `field_inits` has been resolved.
4554 inits_resolved: bool,4563 inits_resolved: bool = false,
4555 // The types and all its fields have had their layout resolved. Even through pointer,4564 // The types and all its fields have had their layout resolved. Even through pointer = false,
4556 // which `layout_resolved` does not ensure.4565 // which `layout_resolved` does not ensure.
4557 fully_resolved: bool,4566 fully_resolved: bool = false,
4558 is_reified: bool,4567 is_reified: bool = false,
4559 _: u6 = 0,4568 _: u6 = 0,
4560 };4569 };
4561 };4570 };
...@@ -5400,40 +5409,46 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -5400,40 +5409,46 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
5400 .type_struct => .{ .struct_type = ns: {5409 .type_struct => .{ .struct_type = ns: {
5401 if (data == 0) break :ns .empty_struct;5410 if (data == 0) break :ns .empty_struct;
5402 const extra_list = unwrapped_index.getExtra(ip);5411 const extra_list = unwrapped_index.getExtra(ip);
5403 const extra = extraDataTrail(extra_list, Tag.TypeStruct, data);5412 const extra_items = extra_list.view().items(.@"0");
5404 if (extra.data.flags.is_reified) {5413 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
5405 assert(!extra.data.flags.any_captures);5414 const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .monotonic));
5415 const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStruct).Struct.fields.len);
5416 if (flags.is_reified) {
5417 assert(!flags.any_captures);
5406 break :ns .{ .reified = .{5418 break :ns .{ .reified = .{
5407 .zir_index = extra.data.zir_index,5419 .zir_index = zir_index,
5408 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),5420 .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(),
5409 } };5421 } };
5410 }5422 }
5411 break :ns .{ .declared = .{5423 break :ns .{ .declared = .{
5412 .zir_index = extra.data.zir_index,5424 .zir_index = zir_index,
5413 .captures = .{ .owned = if (extra.data.flags.any_captures) .{5425 .captures = .{ .owned = if (flags.any_captures) .{
5414 .tid = unwrapped_index.tid,5426 .tid = unwrapped_index.tid,
5415 .start = extra.end + 1,5427 .start = end_extra_index + 1,
5416 .len = extra_list.view().items(.@"0")[extra.end],5428 .len = extra_list.view().items(.@"0")[end_extra_index],
5417 } else CaptureValue.Slice.empty },5429 } else CaptureValue.Slice.empty },
5418 } };5430 } };
5419 } },5431 } },
54205432
5421 .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = ns: {5433 .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = ns: {
5422 const extra_list = unwrapped_index.getExtra(ip);5434 const extra_list = unwrapped_index.getExtra(ip);
5423 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data);5435 const extra_items = extra_list.view().items(.@"0");
5424 if (extra.data.flags.is_reified) {5436 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
5425 assert(!extra.data.flags.any_captures);5437 const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .monotonic));
5438 const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStructPacked).Struct.fields.len);
5439 if (flags.is_reified) {
5440 assert(!flags.any_captures);
5426 break :ns .{ .reified = .{5441 break :ns .{ .reified = .{
5427 .zir_index = extra.data.zir_index,5442 .zir_index = zir_index,
5428 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),5443 .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(),
5429 } };5444 } };
5430 }5445 }
5431 break :ns .{ .declared = .{5446 break :ns .{ .declared = .{
5432 .zir_index = extra.data.zir_index,5447 .zir_index = zir_index,
5433 .captures = .{ .owned = if (extra.data.flags.any_captures) .{5448 .captures = .{ .owned = if (flags.any_captures) .{
5434 .tid = unwrapped_index.tid,5449 .tid = unwrapped_index.tid,
5435 .start = extra.end + 1,5450 .start = end_extra_index + 1,
5436 .len = extra_list.view().items(.@"0")[extra.end],5451 .len = extra_items[end_extra_index],
5437 } else CaptureValue.Slice.empty },5452 } else CaptureValue.Slice.empty },
5438 } };5453 } };
5439 } },5454 } },