authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-02 18:49:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:59-07:00
loge23b0a01e6357252eb2c08a83eff9169ce49042c
tree86742fd9ad29116eddc61c1e093ae8155a435fb4
parent6a15fc87ad62ec0509017c960f6983ce1493c31d

InternPool: fix yet more key lifetime issues


6 files changed, 52 insertions(+), 44 deletions(-)

src/Module.zig+7-8
...@@ -5448,7 +5448,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5448,7 +5448,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5448 defer comptime_mutable_decls.deinit();5448 defer comptime_mutable_decls.deinit();
54495449
5450 const fn_ty = decl.ty;5450 const fn_ty = decl.ty;
5451 const fn_ty_info = mod.typeToFunc(fn_ty).?;
54525451
5453 var sema: Sema = .{5452 var sema: Sema = .{
5454 .mod = mod,5453 .mod = mod,
...@@ -5459,7 +5458,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5459,7 +5458,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5459 .owner_decl_index = decl_index,5458 .owner_decl_index = decl_index,
5460 .func = func,5459 .func = func,
5461 .func_index = func_index.toOptional(),5460 .func_index = func_index.toOptional(),
5462 .fn_ret_ty = fn_ty_info.return_type.toType(),5461 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
5463 .owner_func = func,5462 .owner_func = func,
5464 .owner_func_index = func_index.toOptional(),5463 .owner_func_index = func_index.toOptional(),
5465 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),5464 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
...@@ -5499,7 +5498,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5499,7 +5498,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5499 // This could be a generic function instantiation, however, in which case we need to5498 // This could be a generic function instantiation, however, in which case we need to
5500 // map the comptime parameters to constant values and only emit arg AIR instructions5499 // map the comptime parameters to constant values and only emit arg AIR instructions
5501 // for the runtime ones.5500 // for the runtime ones.
5502 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);5501 const runtime_params_len = @intCast(u32, mod.typeToFunc(fn_ty).?.param_types.len);
5503 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);5502 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
5504 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`5503 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
5505 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);5504 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
...@@ -5525,7 +5524,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5525,7 +5524,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5525 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);5524 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5526 total_param_index += 1;5525 total_param_index += 1;
5527 continue;5526 continue;
5528 } else fn_ty_info.param_types[runtime_param_index].toType();5527 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
55295528
5530 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {5529 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
5531 error.NeededSourceLocation => unreachable,5530 error.NeededSourceLocation => unreachable,
...@@ -5623,7 +5622,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5623,7 +5622,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5623 // Crucially, this happens *after* we set the function state to success above,5622 // Crucially, this happens *after* we set the function state to success above,
5624 // so that dependencies on the function body will now be satisfied rather than5623 // so that dependencies on the function body will now be satisfied rather than
5625 // result in circular dependency errors.5624 // result in circular dependency errors.
5626 sema.resolveFnTypes(mod.typeToFunc(fn_ty).?) catch |err| switch (err) {5625 sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
5627 error.NeededSourceLocation => unreachable,5626 error.NeededSourceLocation => unreachable,
5628 error.GenericPoison => unreachable,5627 error.GenericPoison => unreachable,
5629 error.ComptimeReturn => unreachable,5628 error.ComptimeReturn => unreachable,
...@@ -6378,9 +6377,9 @@ pub fn populateTestFunctions(...@@ -6378,9 +6377,9 @@ pub fn populateTestFunctions(
63786377
6379 for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| {6378 for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| {
6380 const test_decl = mod.declPtr(test_decl_index);6379 const test_decl = mod.declPtr(test_decl_index);
6381 // Protects test_decl_name from being invalidated during call to intern() below.6380 // TODO: write something like getCoercedInts to avoid needing to dupe
6382 try ip.string_bytes.ensureUnusedCapacity(gpa, ip.stringToSlice(test_decl.name).len + 10);6381 const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(test_decl.name));
6383 const test_decl_name = ip.stringToSlice(test_decl.name);6382 defer gpa.free(test_decl_name);
6384 const test_name_decl_index = n: {6383 const test_name_decl_index = n: {
6385 const test_name_decl_ty = try mod.arrayType(.{6384 const test_name_decl_ty = try mod.arrayType(.{
6386 .len = test_decl_name.len,6385 .len = test_decl_name.len,
src/Sema.zig+35-26
...@@ -5227,6 +5227,8 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -5227,6 +5227,8 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
5227fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {5227fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {
5228 const mod = sema.mod;5228 const mod = sema.mod;
5229 const gpa = sema.gpa;5229 const gpa = sema.gpa;
5230 // TODO: write something like getCoercedInts to avoid needing to dupe
5231 const duped_bytes = try sema.arena.dupe(u8, bytes);
5230 const ty = try mod.arrayType(.{5232 const ty = try mod.arrayType(.{
5231 .len = bytes.len,5233 .len = bytes.len,
5232 .child = .u8_type,5234 .child = .u8_type,
...@@ -5234,7 +5236,7 @@ fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Ins...@@ -5234,7 +5236,7 @@ fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Ins
5234 });5236 });
5235 const val = try mod.intern(.{ .aggregate = .{5237 const val = try mod.intern(.{ .aggregate = .{
5236 .ty = ty.toIntern(),5238 .ty = ty.toIntern(),
5237 .storage = .{ .bytes = bytes },5239 .storage = .{ .bytes = duped_bytes },
5238 } });5240 } });
5239 const gop = try mod.memoized_decls.getOrPut(gpa, val);5241 const gop = try mod.memoized_decls.getOrPut(gpa, val);
5240 if (!gop.found_existing) {5242 if (!gop.found_existing) {
...@@ -11478,7 +11480,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11478,7 +11480,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11478 operand_ty.fmt(mod),11480 operand_ty.fmt(mod),
11479 });11481 });
11480 }11482 }
11481 for (operand_ty.errorSetNames(mod)) |error_name_ip| {11483 for (0..operand_ty.errorSetNames(mod).len) |i| {
11484 const error_name_ip = operand_ty.errorSetNames(mod)[i];
11482 const error_name = mod.intern_pool.stringToSlice(error_name_ip);11485 const error_name = mod.intern_pool.stringToSlice(error_name_ip);
11483 if (seen_errors.contains(error_name)) continue;11486 if (seen_errors.contains(error_name)) continue;
11484 cases_len += 1;11487 cases_len += 1;
...@@ -15851,7 +15854,8 @@ fn zirBuiltinSrc(...@@ -15851,7 +15854,8 @@ fn zirBuiltinSrc(
15851 const func_name_val = blk: {15854 const func_name_val = blk: {
15852 var anon_decl = try block.startAnonDecl();15855 var anon_decl = try block.startAnonDecl();
15853 defer anon_decl.deinit();15856 defer anon_decl.deinit();
15854 const name = mod.intern_pool.stringToSlice(fn_owner_decl.name);15857 // TODO: write something like getCoercedInts to avoid needing to dupe
15858 const name = try sema.arena.dupe(u8, mod.intern_pool.stringToSlice(fn_owner_decl.name));
15855 const new_decl_ty = try mod.arrayType(.{15859 const new_decl_ty = try mod.arrayType(.{
15856 .len = name.len,15860 .len = name.len,
15857 .child = .u8_type,15861 .child = .u8_type,
...@@ -16287,7 +16291,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16287,7 +16291,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16287 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {16291 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
16288 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);16292 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);
16289 for (vals, 0..) |*field_val, i| {16293 for (vals, 0..) |*field_val, i| {
16290 const name = ip.stringToSlice(ty.errorSetNames(mod)[i]);16294 // TODO: write something like getCoercedInts to avoid needing to dupe
16295 const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i]));
16291 const name_val = v: {16296 const name_val = v: {
16292 var anon_decl = try block.startAnonDecl();16297 var anon_decl = try block.startAnonDecl();
16293 defer anon_decl.deinit();16298 defer anon_decl.deinit();
...@@ -16417,8 +16422,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16417,8 +16422,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1641716422
16418 const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_type.names.len);16423 const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_type.names.len);
16419 for (enum_field_vals, 0..) |*field_val, i| {16424 for (enum_field_vals, 0..) |*field_val, i| {
16420 const name_ip = ip.indexToKey(ty.toIntern()).enum_type.names[i];16425 // TODO: write something like getCoercedInts to avoid needing to dupe
16421 const name = ip.stringToSlice(name_ip);16426 const name = try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).enum_type.names[i]));
16422 const name_val = v: {16427 const name_val = v: {
16423 var anon_decl = try block.startAnonDecl();16428 var anon_decl = try block.startAnonDecl();
16424 defer anon_decl.deinit();16429 defer anon_decl.deinit();
...@@ -16556,7 +16561,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16556,7 +16561,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1655616561
16557 for (union_field_vals, 0..) |*field_val, i| {16562 for (union_field_vals, 0..) |*field_val, i| {
16558 const field = union_fields.values()[i];16563 const field = union_fields.values()[i];
16559 const name = ip.stringToSlice(union_fields.keys()[i]);16564 // TODO: write something like getCoercedInts to avoid needing to dupe
16565 const name = try sema.arena.dupe(u8, ip.stringToSlice(union_fields.keys()[i]));
16560 const name_val = v: {16566 const name_val = v: {
16561 var anon_decl = try block.startAnonDecl();16567 var anon_decl = try block.startAnonDecl();
16562 defer anon_decl.deinit();16568 defer anon_decl.deinit();
...@@ -16714,9 +16720,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16714,9 +16720,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16714 const name_val = v: {16720 const name_val = v: {
16715 var anon_decl = try block.startAnonDecl();16721 var anon_decl = try block.startAnonDecl();
16716 defer anon_decl.deinit();16722 defer anon_decl.deinit();
16723 // TODO: write something like getCoercedInts to avoid needing to dupe
16717 const bytes = if (tuple.names.len != 0)16724 const bytes = if (tuple.names.len != 0)
16718 // https://github.com/ziglang/zig/issues/1570916725 // https://github.com/ziglang/zig/issues/15709
16719 @as([]const u8, ip.stringToSlice(tuple.names[i]))16726 try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(struct_ty.toIntern()).anon_struct_type.names[i]))
16720 else16727 else
16721 try std.fmt.allocPrint(sema.arena, "{d}", .{i});16728 try std.fmt.allocPrint(sema.arena, "{d}", .{i});
16722 const new_decl_ty = try mod.arrayType(.{16729 const new_decl_ty = try mod.arrayType(.{
...@@ -16771,7 +16778,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16771,7 +16778,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16771 struct_obj.fields.keys(),16778 struct_obj.fields.keys(),
16772 struct_obj.fields.values(),16779 struct_obj.fields.values(),
16773 ) |*field_val, name_nts, field| {16780 ) |*field_val, name_nts, field| {
16774 const name = ip.stringToSlice(name_nts);16781 // TODO: write something like getCoercedInts to avoid needing to dupe
16782 const name = try sema.arena.dupe(u8, ip.stringToSlice(name_nts));
16775 const name_val = v: {16783 const name_val = v: {
16776 var anon_decl = try block.startAnonDecl();16784 var anon_decl = try block.startAnonDecl();
16777 defer anon_decl.deinit();16785 defer anon_decl.deinit();
...@@ -17020,9 +17028,8 @@ fn typeInfoNamespaceDecls(...@@ -17020,9 +17028,8 @@ fn typeInfoNamespaceDecls(
17020 const name_val = v: {17028 const name_val = v: {
17021 var anon_decl = try block.startAnonDecl();17029 var anon_decl = try block.startAnonDecl();
17022 defer anon_decl.deinit();17030 defer anon_decl.deinit();
17023 // Protects the decl name slice from being invalidated at the call to intern().17031 // TODO: write something like getCoercedInts to avoid needing to dupe
17024 try ip.string_bytes.ensureUnusedCapacity(sema.gpa, ip.stringToSlice(decl.name).len + 1);17032 const name = try sema.arena.dupe(u8, ip.stringToSlice(decl.name));
17025 const name = ip.stringToSlice(decl.name);
17026 const new_decl_ty = try mod.arrayType(.{17033 const new_decl_ty = try mod.arrayType(.{
17027 .len = name.len,17034 .len = name.len,
17028 .child = .u8_type,17035 .child = .u8_type,
...@@ -19060,6 +19067,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19060,6 +19067,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19060 };19067 };
19061 return sema.failWithOwnedErrorMsg(msg);19068 return sema.failWithOwnedErrorMsg(msg);
19062 };19069 };
19070 // TODO: write something like getCoercedInts to avoid needing to dupe
19063 const field_name = enum_ty.enumFieldName(field_index, mod);19071 const field_name = enum_ty.enumFieldName(field_index, mod);
19064 return sema.addStrLit(block, ip.stringToSlice(field_name));19072 return sema.addStrLit(block, ip.stringToSlice(field_name));
19065 }19073 }
...@@ -19601,7 +19609,6 @@ fn zirReify(...@@ -19601,7 +19609,6 @@ fn zirReify(
19601 // Tag type19609 // Tag type
19602 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));19610 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
19603 var explicit_tags_seen: []bool = &.{};19611 var explicit_tags_seen: []bool = &.{};
19604 var explicit_enum_info: ?InternPool.Key.EnumType = null;
19605 var enum_field_names: []InternPool.NullTerminatedString = &.{};19612 var enum_field_names: []InternPool.NullTerminatedString = &.{};
19606 if (tag_type_val.optionalValue(mod)) |payload_val| {19613 if (tag_type_val.optionalValue(mod)) |payload_val| {
19607 union_obj.tag_ty = payload_val.toType();19614 union_obj.tag_ty = payload_val.toType();
...@@ -19611,7 +19618,6 @@ fn zirReify(...@@ -19611,7 +19618,6 @@ fn zirReify(
19611 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),19618 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
19612 };19619 };
1961319620
19614 explicit_enum_info = enum_type;
19615 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);19621 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
19616 @memset(explicit_tags_seen, false);19622 @memset(explicit_tags_seen, false);
19617 } else {19623 } else {
...@@ -19640,7 +19646,8 @@ fn zirReify(...@@ -19640,7 +19646,8 @@ fn zirReify(
19640 enum_field_names[i] = field_name;19646 enum_field_names[i] = field_name;
19641 }19647 }
1964219648
19643 if (explicit_enum_info) |tag_info| {19649 if (explicit_tags_seen.len > 0) {
19650 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
19644 const enum_index = tag_info.nameIndex(ip, field_name) orelse {19651 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
19645 const msg = msg: {19652 const msg = msg: {
19646 const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ ip.stringToSlice(field_name), union_obj.tag_ty.fmt(mod) });19653 const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ ip.stringToSlice(field_name), union_obj.tag_ty.fmt(mod) });
...@@ -19705,7 +19712,8 @@ fn zirReify(...@@ -19705,7 +19712,8 @@ fn zirReify(
19705 }19712 }
19706 }19713 }
1970719714
19708 if (explicit_enum_info) |tag_info| {19715 if (explicit_tags_seen.len > 0) {
19716 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
19709 if (tag_info.names.len > fields_len) {19717 if (tag_info.names.len > fields_len) {
19710 const msg = msg: {19718 const msg = msg: {
19711 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});19719 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
...@@ -31625,17 +31633,17 @@ fn resolvePeerTypes(...@@ -31625,17 +31633,17 @@ fn resolvePeerTypes(
31625 return chosen_ty;31633 return chosen_ty;
31626}31634}
3162731635
31628pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileError!void {31636pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
31629 const mod = sema.mod;31637 const mod = sema.mod;
31630 try sema.resolveTypeFully(fn_info.return_type.toType());31638 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType());
3163131639
31632 if (mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.toType().isError(mod)) {31640 if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) {
31633 // Ensure the type exists so that backends can assume that.31641 // Ensure the type exists so that backends can assume that.
31634 _ = try sema.getBuiltinType("StackTrace");31642 _ = try sema.getBuiltinType("StackTrace");
31635 }31643 }
3163631644
31637 for (fn_info.param_types) |param_ty| {31645 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
31638 try sema.resolveTypeFully(param_ty.toType());31646 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
31639 }31647 }
31640}31648}
3164131649
...@@ -33077,7 +33085,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -33077,7 +33085,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
33077 var enum_field_names: []InternPool.NullTerminatedString = &.{};33085 var enum_field_names: []InternPool.NullTerminatedString = &.{};
33078 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};33086 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
33079 var explicit_tags_seen: []bool = &.{};33087 var explicit_tags_seen: []bool = &.{};
33080 var explicit_enum_info: ?InternPool.Key.EnumType = null;
33081 if (tag_type_ref != .none) {33088 if (tag_type_ref != .none) {
33082 const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };33089 const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
33083 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);33090 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
...@@ -33114,7 +33121,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -33114,7 +33121,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
33114 };33121 };
33115 // The fields of the union must match the enum exactly.33122 // The fields of the union must match the enum exactly.
33116 // A flag per field is used to check for missing and extraneous fields.33123 // A flag per field is used to check for missing and extraneous fields.
33117 explicit_enum_info = enum_type;
33118 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);33124 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
33119 @memset(explicit_tags_seen, false);33125 @memset(explicit_tags_seen, false);
33120 }33126 }
...@@ -33256,7 +33262,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -33256,7 +33262,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
33256 return sema.failWithOwnedErrorMsg(msg);33262 return sema.failWithOwnedErrorMsg(msg);
33257 }33263 }
3325833264
33259 if (explicit_enum_info) |tag_info| {33265 if (explicit_tags_seen.len > 0) {
33266 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
33260 const enum_index = tag_info.nameIndex(ip, field_name) orelse {33267 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
33261 const msg = msg: {33268 const msg = msg: {
33262 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{33269 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
...@@ -33346,7 +33353,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -33346,7 +33353,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
33346 }33353 }
33347 }33354 }
3334833355
33349 if (explicit_enum_info) |tag_info| {33356 if (explicit_tags_seen.len > 0) {
33357 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
33350 if (tag_info.names.len > fields_len) {33358 if (tag_info.names.len > fields_len) {
33351 const msg = msg: {33359 const msg = msg: {
33352 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});33360 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});
...@@ -33706,9 +33714,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33706,9 +33714,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33706 }33714 }
33707 // In this case the struct has all comptime-known fields and33715 // In this case the struct has all comptime-known fields and
33708 // therefore has one possible value.33716 // therefore has one possible value.
33717 // TODO: write something like getCoercedInts to avoid needing to dupe
33709 return (try mod.intern(.{ .aggregate = .{33718 return (try mod.intern(.{ .aggregate = .{
33710 .ty = ty.toIntern(),33719 .ty = ty.toIntern(),
33711 .storage = .{ .elems = tuple.values },33720 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },
33712 } })).toValue();33721 } })).toValue();
33713 },33722 },
3371433723
src/arch/x86_64/CodeGen.zig+2-6
...@@ -2026,13 +2026,9 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -2026,13 +2026,9 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2026 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });2026 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
20272027
2028 var data_off: i32 = 0;2028 var data_off: i32 = 0;
2029 for (2029 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| {
2030 exitlude_jump_relocs,
2031 enum_ty.enumFields(mod),
2032 0..,
2033 ) |*exitlude_jump_reloc, tag_name_ip, index_usize| {
2034 const index = @intCast(u32, index_usize);2030 const index = @intCast(u32, index_usize);
2035 const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);2031 const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]);
2036 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);2032 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
2037 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });2033 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
2038 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);2034 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
src/codegen.zig+1-1
...@@ -517,7 +517,7 @@ pub fn generateSymbol(...@@ -517,7 +517,7 @@ pub fn generateSymbol(
517 const field_ty = field.ty;517 const field_ty = field.ty;
518 if (!field_ty.hasRuntimeBits(mod)) continue;518 if (!field_ty.hasRuntimeBits(mod)) continue;
519519
520 const field_val = switch (aggregate.storage) {520 const field_val = switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
521 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{521 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
522 .ty = field_ty.toIntern(),522 .ty = field_ty.toIntern(),
523 .storage = .{ .u64 = bytes[index] },523 .storage = .{ .u64 = bytes[index] },
src/type.zig+4-1
...@@ -2576,9 +2576,12 @@ pub const Type = struct {...@@ -2576,9 +2576,12 @@ pub const Type = struct {
2576 }2576 }
2577 // In this case the struct has all comptime-known fields and2577 // In this case the struct has all comptime-known fields and
2578 // therefore has one possible value.2578 // therefore has one possible value.
2579 // TODO: write something like getCoercedInts to avoid needing to dupe
2580 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values);
2581 defer mod.gpa.free(duped_values);
2579 return (try mod.intern(.{ .aggregate = .{2582 return (try mod.intern(.{ .aggregate = .{
2580 .ty = ty.toIntern(),2583 .ty = ty.toIntern(),
2581 .storage = .{ .elems = tuple.values },2584 .storage = .{ .elems = duped_values },
2582 } })).toValue();2585 } })).toValue();
2583 },2586 },
25842587
src/value.zig+3-2
...@@ -1904,6 +1904,7 @@ pub const Value = struct {...@@ -1904,6 +1904,7 @@ pub const Value = struct {
1904 start: usize,1904 start: usize,
1905 end: usize,1905 end: usize,
1906 ) error{OutOfMemory}!Value {1906 ) error{OutOfMemory}!Value {
1907 // TODO: write something like getCoercedInts to avoid needing to dupe
1907 return switch (val.ip_index) {1908 return switch (val.ip_index) {
1908 .none => switch (val.tag()) {1909 .none => switch (val.tag()) {
1909 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),1910 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
...@@ -1937,8 +1938,8 @@ pub const Value = struct {...@@ -1937,8 +1938,8 @@ pub const Value = struct {
1937 else => unreachable,1938 else => unreachable,
1938 }.toIntern(),1939 }.toIntern(),
1939 .storage = switch (aggregate.storage) {1940 .storage = switch (aggregate.storage) {
1940 .bytes => |bytes| .{ .bytes = bytes[start..end] },1941 .bytes => .{ .bytes = try arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) },
1941 .elems => |elems| .{ .elems = elems[start..end] },1942 .elems => .{ .elems = try arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) },
1942 .repeated_elem => |elem| .{ .repeated_elem = elem },1943 .repeated_elem => |elem| .{ .repeated_elem = elem },
1943 },1944 },
1944 } })).toValue(),1945 } })).toValue(),