diff --git a/src/InternPool.zig b/src/InternPool.zig index 6639603cb5..6a82abedce 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -6810,17 +6810,13 @@ pub const WipEnumType = struct { names_start: u32, values_map: OptionalMapIndex, values_start: u32, - expected_fields_len: if (std.debug.runtime_safety) u32 else void, pub fn prepare( wip: WipEnumType, ip: *InternPool, decl: DeclIndex, namespace: OptionalNamespaceIndex, - tag_ty: Index, ) void { - assert(ip.isIntegerType(tag_ty)); - ip.extra.items[wip.tag_ty_index] = @intFromEnum(tag_ty); ip.extra.items[wip.decl_index] = @intFromEnum(decl); if (wip.namespace_index) |i| { ip.extra.items[i] = @intFromEnum(namespace.unwrap().?); @@ -6829,6 +6825,11 @@ pub const WipEnumType = struct { } } + pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void { + assert(ip.isIntegerType(tag_ty)); + ip.extra.items[wip.tag_ty_index] = @intFromEnum(tag_ty); + } + pub const FieldConflict = struct { kind: enum { name, value }, prev_field_idx: u32, @@ -6858,18 +6859,6 @@ pub const WipEnumType = struct { return null; } - pub fn finish(wip: WipEnumType, ip: *InternPool) Index { - if (std.debug.runtime_safety) { - const names_map = &ip.maps.items[@intFromEnum(wip.names_map)]; - assert(names_map.count() == wip.expected_fields_len); - if (wip.values_map.unwrap()) |v| { - const values_map = &ip.maps.items[@intFromEnum(v)]; - assert(values_map.count() == wip.expected_fields_len); - } - } - return wip.index; - } - pub fn cancel(wip: WipEnumType, ip: *InternPool) void { ip.remove(wip.index); } @@ -6951,7 +6940,6 @@ pub fn getEnumType( .names_start = @intCast(names_start), .values_map = .none, .values_start = undefined, - .expected_fields_len = if (std.debug.runtime_safety) ini.fields_len else {}, } }; }, .explicit, .nonexhaustive => { @@ -7016,7 +7004,6 @@ pub fn getEnumType( .names_start = @intCast(names_start), .values_map = values_map, .values_start = @intCast(values_start), - .expected_fields_len = if (std.debug.runtime_safety) ini.fields_len else {}, } }; }, } diff --git a/src/Sema.zig b/src/Sema.zig index c3e0d5991e..2ea7432c0e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2993,7 +2993,12 @@ fn zirEnumDecl( }, .existing => |ty| return Air.internedToRef(ty), }; - errdefer wip_ty.cancel(ip); + + // Once this is `true`, we will not delete the decl or type even upon failure, since we + // have finished constructing the type and are in the process of analyzing it. + var done = false; + + errdefer if (!done) wip_ty.cancel(ip); const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ .ty = Type.type, @@ -3001,7 +3006,7 @@ fn zirEnumDecl( }, small.name_strategy, "enum", inst); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; - errdefer mod.abortAnonDecl(new_decl_index); + errdefer if (!done) mod.abortAnonDecl(new_decl_index); if (sema.mod.comp.debug_incremental) { try mod.intern_pool.addDependency( @@ -3017,12 +3022,17 @@ fn zirEnumDecl( .decl_index = new_decl_index, .file_scope = block.getFileScope(mod), })).toOptional() else .none; - errdefer if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns); + errdefer if (!done) if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns); if (new_namespace_index.unwrap()) |ns| { try mod.scanNamespace(ns, decls, new_decl); } + // We've finished the initial construction of this type, and are about to perform analysis. + // Set the decl and namespace appropriately, and don't destroy anything on failure. + wip_ty.prepare(ip, new_decl_index, new_namespace_index); + done = true; + const int_tag_ty = ty: { // We create a block for the field type instructions because they // may need to reference Decls from inside the enum namespace. @@ -3075,7 +3085,7 @@ fn zirEnumDecl( } }; - wip_ty.prepare(ip, new_decl_index, new_namespace_index, int_tag_ty.toIntern()); + wip_ty.setTagTy(ip, int_tag_ty.toIntern()); if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) { @@ -3177,7 +3187,7 @@ fn zirEnumDecl( } try mod.finalizeAnonDecl(new_decl_index); - return Air.internedToRef(wip_ty.finish(ip)); + return Air.internedToRef(wip_ty.index); } fn zirUnionDecl( @@ -21537,7 +21547,8 @@ fn reifyEnum( mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); - wip_ty.prepare(ip, new_decl_index, .none, tag_ty.toIntern()); + wip_ty.prepare(ip, new_decl_index, .none); + wip_ty.setTagTy(ip, tag_ty.toIntern()); for (0..fields_len) |field_idx| { const field_info = try fields_val.elemValue(mod, field_idx); @@ -21582,7 +21593,7 @@ fn reifyEnum( } try mod.finalizeAnonDecl(new_decl_index); - return Air.internedToRef(wip_ty.finish(ip)); + return Air.internedToRef(wip_ty.index); } fn reifyUnion(