authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-05 13:12:28+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-06 21:26:38+00:00
log4c05a9a892d68749f3d7da26ee0e884158640720
tree0fca45e4c519f04b7904d5004cc9a42c097ee489
parente1d8187028ec6df7fbf420d3e4b56da8bf3dcf0a
signaturelock-open Commit is signed but in an unrecognized format.

Sema: do not destroy enum type if field analysis fails


2 files changed, 23 insertions(+), 25 deletions(-)

src/InternPool.zig+5-18
...@@ -6810,17 +6810,13 @@ pub const WipEnumType = struct {...@@ -6810,17 +6810,13 @@ pub const WipEnumType = struct {
6810 names_start: u32,6810 names_start: u32,
6811 values_map: OptionalMapIndex,6811 values_map: OptionalMapIndex,
6812 values_start: u32,6812 values_start: u32,
6813 expected_fields_len: if (std.debug.runtime_safety) u32 else void,
68146813
6815 pub fn prepare(6814 pub fn prepare(
6816 wip: WipEnumType,6815 wip: WipEnumType,
6817 ip: *InternPool,6816 ip: *InternPool,
6818 decl: DeclIndex,6817 decl: DeclIndex,
6819 namespace: OptionalNamespaceIndex,6818 namespace: OptionalNamespaceIndex,
6820 tag_ty: Index,
6821 ) void {6819 ) void {
6822 assert(ip.isIntegerType(tag_ty));
6823 ip.extra.items[wip.tag_ty_index] = @intFromEnum(tag_ty);
6824 ip.extra.items[wip.decl_index] = @intFromEnum(decl);6820 ip.extra.items[wip.decl_index] = @intFromEnum(decl);
6825 if (wip.namespace_index) |i| {6821 if (wip.namespace_index) |i| {
6826 ip.extra.items[i] = @intFromEnum(namespace.unwrap().?);6822 ip.extra.items[i] = @intFromEnum(namespace.unwrap().?);
...@@ -6829,6 +6825,11 @@ pub const WipEnumType = struct {...@@ -6829,6 +6825,11 @@ pub const WipEnumType = struct {
6829 }6825 }
6830 }6826 }
68316827
6828 pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void {
6829 assert(ip.isIntegerType(tag_ty));
6830 ip.extra.items[wip.tag_ty_index] = @intFromEnum(tag_ty);
6831 }
6832
6832 pub const FieldConflict = struct {6833 pub const FieldConflict = struct {
6833 kind: enum { name, value },6834 kind: enum { name, value },
6834 prev_field_idx: u32,6835 prev_field_idx: u32,
...@@ -6858,18 +6859,6 @@ pub const WipEnumType = struct {...@@ -6858,18 +6859,6 @@ pub const WipEnumType = struct {
6858 return null;6859 return null;
6859 }6860 }
68606861
6861 pub fn finish(wip: WipEnumType, ip: *InternPool) Index {
6862 if (std.debug.runtime_safety) {
6863 const names_map = &ip.maps.items[@intFromEnum(wip.names_map)];
6864 assert(names_map.count() == wip.expected_fields_len);
6865 if (wip.values_map.unwrap()) |v| {
6866 const values_map = &ip.maps.items[@intFromEnum(v)];
6867 assert(values_map.count() == wip.expected_fields_len);
6868 }
6869 }
6870 return wip.index;
6871 }
6872
6873 pub fn cancel(wip: WipEnumType, ip: *InternPool) void {6862 pub fn cancel(wip: WipEnumType, ip: *InternPool) void {
6874 ip.remove(wip.index);6863 ip.remove(wip.index);
6875 }6864 }
...@@ -6951,7 +6940,6 @@ pub fn getEnumType(...@@ -6951,7 +6940,6 @@ pub fn getEnumType(
6951 .names_start = @intCast(names_start),6940 .names_start = @intCast(names_start),
6952 .values_map = .none,6941 .values_map = .none,
6953 .values_start = undefined,6942 .values_start = undefined,
6954 .expected_fields_len = if (std.debug.runtime_safety) ini.fields_len else {},
6955 } };6943 } };
6956 },6944 },
6957 .explicit, .nonexhaustive => {6945 .explicit, .nonexhaustive => {
...@@ -7016,7 +7004,6 @@ pub fn getEnumType(...@@ -7016,7 +7004,6 @@ pub fn getEnumType(
7016 .names_start = @intCast(names_start),7004 .names_start = @intCast(names_start),
7017 .values_map = values_map,7005 .values_map = values_map,
7018 .values_start = @intCast(values_start),7006 .values_start = @intCast(values_start),
7019 .expected_fields_len = if (std.debug.runtime_safety) ini.fields_len else {},
7020 } };7007 } };
7021 },7008 },
7022 }7009 }
src/Sema.zig+18-7
...@@ -2993,7 +2993,12 @@ fn zirEnumDecl(...@@ -2993,7 +2993,12 @@ fn zirEnumDecl(
2993 },2993 },
2994 .existing => |ty| return Air.internedToRef(ty),2994 .existing => |ty| return Air.internedToRef(ty),
2995 };2995 };
2996 errdefer wip_ty.cancel(ip);2996
2997 // Once this is `true`, we will not delete the decl or type even upon failure, since we
2998 // have finished constructing the type and are in the process of analyzing it.
2999 var done = false;
3000
3001 errdefer if (!done) wip_ty.cancel(ip);
29973002
2998 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{3003 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
2999 .ty = Type.type,3004 .ty = Type.type,
...@@ -3001,7 +3006,7 @@ fn zirEnumDecl(...@@ -3001,7 +3006,7 @@ fn zirEnumDecl(
3001 }, small.name_strategy, "enum", inst);3006 }, small.name_strategy, "enum", inst);
3002 const new_decl = mod.declPtr(new_decl_index);3007 const new_decl = mod.declPtr(new_decl_index);
3003 new_decl.owns_tv = true;3008 new_decl.owns_tv = true;
3004 errdefer mod.abortAnonDecl(new_decl_index);3009 errdefer if (!done) mod.abortAnonDecl(new_decl_index);
30053010
3006 if (sema.mod.comp.debug_incremental) {3011 if (sema.mod.comp.debug_incremental) {
3007 try mod.intern_pool.addDependency(3012 try mod.intern_pool.addDependency(
...@@ -3017,12 +3022,17 @@ fn zirEnumDecl(...@@ -3017,12 +3022,17 @@ fn zirEnumDecl(
3017 .decl_index = new_decl_index,3022 .decl_index = new_decl_index,
3018 .file_scope = block.getFileScope(mod),3023 .file_scope = block.getFileScope(mod),
3019 })).toOptional() else .none;3024 })).toOptional() else .none;
3020 errdefer if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns);3025 errdefer if (!done) if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns);
30213026
3022 if (new_namespace_index.unwrap()) |ns| {3027 if (new_namespace_index.unwrap()) |ns| {
3023 try mod.scanNamespace(ns, decls, new_decl);3028 try mod.scanNamespace(ns, decls, new_decl);
3024 }3029 }
30253030
3031 // We've finished the initial construction of this type, and are about to perform analysis.
3032 // Set the decl and namespace appropriately, and don't destroy anything on failure.
3033 wip_ty.prepare(ip, new_decl_index, new_namespace_index);
3034 done = true;
3035
3026 const int_tag_ty = ty: {3036 const int_tag_ty = ty: {
3027 // We create a block for the field type instructions because they3037 // We create a block for the field type instructions because they
3028 // may need to reference Decls from inside the enum namespace.3038 // may need to reference Decls from inside the enum namespace.
...@@ -3075,7 +3085,7 @@ fn zirEnumDecl(...@@ -3075,7 +3085,7 @@ fn zirEnumDecl(
3075 }3085 }
3076 };3086 };
30773087
3078 wip_ty.prepare(ip, new_decl_index, new_namespace_index, int_tag_ty.toIntern());3088 wip_ty.setTagTy(ip, int_tag_ty.toIntern());
30793089
3080 if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {3090 if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
3081 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) {3091 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) {
...@@ -3177,7 +3187,7 @@ fn zirEnumDecl(...@@ -3177,7 +3187,7 @@ fn zirEnumDecl(
3177 }3187 }
31783188
3179 try mod.finalizeAnonDecl(new_decl_index);3189 try mod.finalizeAnonDecl(new_decl_index);
3180 return Air.internedToRef(wip_ty.finish(ip));3190 return Air.internedToRef(wip_ty.index);
3181}3191}
31823192
3183fn zirUnionDecl(3193fn zirUnionDecl(
...@@ -21537,7 +21547,8 @@ fn reifyEnum(...@@ -21537,7 +21547,8 @@ fn reifyEnum(
21537 mod.declPtr(new_decl_index).owns_tv = true;21547 mod.declPtr(new_decl_index).owns_tv = true;
21538 errdefer mod.abortAnonDecl(new_decl_index);21548 errdefer mod.abortAnonDecl(new_decl_index);
2153921549
21540 wip_ty.prepare(ip, new_decl_index, .none, tag_ty.toIntern());21550 wip_ty.prepare(ip, new_decl_index, .none);
21551 wip_ty.setTagTy(ip, tag_ty.toIntern());
2154121552
21542 for (0..fields_len) |field_idx| {21553 for (0..fields_len) |field_idx| {
21543 const field_info = try fields_val.elemValue(mod, field_idx);21554 const field_info = try fields_val.elemValue(mod, field_idx);
...@@ -21582,7 +21593,7 @@ fn reifyEnum(...@@ -21582,7 +21593,7 @@ fn reifyEnum(
21582 }21593 }
2158321594
21584 try mod.finalizeAnonDecl(new_decl_index);21595 try mod.finalizeAnonDecl(new_decl_index);
21585 return Air.internedToRef(wip_ty.finish(ip));21596 return Air.internedToRef(wip_ty.index);
21586}21597}
2158721598
21588fn reifyUnion(21599fn reifyUnion(