@@ -3190,6 +3190,15 @@ fn zirEnumDecl(
31903190
31913191 try sema.declareDependency(.{ .interned = new_ty });
31923192 try sema.addTypeReferenceEntry(src, new_ty);
3193+
3194+ // Since this is an enum, it has to be resolved immediately.
3195+ // `ensureTypeUpToDate` has resolved the new type if necessary.
3196+ // We just need to check for resolution failures.
3197+ const ty_unit: AnalUnit = .wrap(.{ .type = new_ty });
3198+ if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) {
3199+ return error.AnalysisFail;
3200+ }
3201+
31933202 return Air.internedToRef(new_ty);
31943203 },
31953204 .wip => |wip| wip,
@@ -17801,12 +17810,23 @@ fn zirThis(
1780117810) CompileError!Air.Inst.Ref {
1780217811 _ = extended;
1780317812 const pt = sema.pt;
17813+ const zcu = pt.zcu;
1780417814 const namespace = pt.zcu.namespacePtr(block.namespace);
1780517815
1780617816 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
1780717817
1780817818 switch (pt.zcu.intern_pool.indexToKey(new_ty)) {
17809- .struct_type, .union_type, .enum_type => try sema.declareDependency(.{ .interned = new_ty }),
17819+ .struct_type, .union_type => try sema.declareDependency(.{ .interned = new_ty }),
17820+ .enum_type => {
17821+ try sema.declareDependency(.{ .interned = new_ty });
17822+ // Since this is an enum, it has to be resolved immediately.
17823+ // `ensureTypeUpToDate` has resolved the new type if necessary.
17824+ // We just need to check for resolution failures.
17825+ const ty_unit: AnalUnit = .wrap(.{ .type = new_ty });
17826+ if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) {
17827+ return error.AnalysisFail;
17828+ }
17829+ },
1781017830 .opaque_type => {},
1781117831 else => unreachable,
1781217832 }
@@ -28478,6 +28498,10 @@ fn unionFieldPtr(
2847828498 if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: {
2847928499 switch (union_obj.flagsUnordered(ip).layout) {
2848028500 .auto => if (initializing) {
28501+ if (!sema.isComptimeMutablePtr(union_ptr_val)) {
28502+ // The initialization is a runtime operation.
28503+ break :ct;
28504+ }
2848128505 // Store to the union to initialize the tag.
2848228506 const field_tag = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
2848328507 const payload_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
@@ -38330,30 +38354,24 @@ pub fn resolveDeclaredEnum(
3833038354 fields_len: u32,
3833138355 zir: Zir,
3833238356 body_end: usize,
38333- ) Zcu.CompileError !void {
38357+ ) Zcu.SemaError !void {
3833438358 const zcu = pt.zcu;
3833538359 const gpa = zcu.gpa;
38336- const ip = &zcu.intern_pool;
38337-
38338- const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3833938360
3834038361 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
38341- const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
3834238362
38343- const anal_unit = AnalUnit.wrap(.{ .type = wip_ty.index });
38344-
38345- var arena = std.heap.ArenaAllocator.init(gpa);
38363+ var arena: std.heap.ArenaAllocator = .init(gpa);
3834638364 defer arena.deinit();
3834738365
38348- var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);
38366+ var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
3834938367 defer comptime_err_ret_trace.deinit();
3835038368
3835138369 var sema: Sema = .{
3835238370 .pt = pt,
3835338371 .gpa = gpa,
3835438372 .arena = arena.allocator(),
3835538373 .code = zir,
38356- .owner = anal_unit ,
38374+ .owner = .wrap(.{ .type = wip_ty.index }) ,
3835738375 .func_index = .none,
3835838376 .func_is_naked = false,
3835938377 .fn_ret_ty = Type.void,
@@ -38379,15 +38397,66 @@ pub fn resolveDeclaredEnum(
3837938397 };
3838038398 defer block.instructions.deinit(gpa);
3838138399
38400+ sema.resolveDeclaredEnumInner(
38401+ &block,
38402+ wip_ty,
38403+ inst,
38404+ tracked_inst,
38405+ src,
38406+ small,
38407+ body,
38408+ tag_type_ref,
38409+ any_values,
38410+ fields_len,
38411+ zir,
38412+ body_end,
38413+ ) catch |err| switch (err) {
38414+ error.GenericPoison => unreachable,
38415+ error.ComptimeBreak => unreachable,
38416+ error.ComptimeReturn => unreachable,
38417+ error.OutOfMemory => |e| return e,
38418+ error.AnalysisFail => {
38419+ if (!zcu.failed_analysis.contains(sema.owner)) {
38420+ try zcu.transitive_failed_analysis.put(gpa, sema.owner, {});
38421+ }
38422+ return error.AnalysisFail;
38423+ },
38424+ };
38425+ }
38426+
38427+ fn resolveDeclaredEnumInner(
38428+ sema: *Sema,
38429+ block: *Block,
38430+ wip_ty: InternPool.WipEnumType,
38431+ inst: Zir.Inst.Index,
38432+ tracked_inst: InternPool.TrackedInst.Index,
38433+ src: LazySrcLoc,
38434+ small: Zir.Inst.EnumDecl.Small,
38435+ body: []const Zir.Inst.Index,
38436+ tag_type_ref: Zir.Inst.Ref,
38437+ any_values: bool,
38438+ fields_len: u32,
38439+ zir: Zir,
38440+ body_end: usize,
38441+ ) Zcu.CompileError!void {
38442+ const pt = sema.pt;
38443+ const zcu = pt.zcu;
38444+ const gpa = zcu.gpa;
38445+ const ip = &zcu.intern_pool;
38446+
38447+ const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
38448+
38449+ const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
38450+
3838238451 const int_tag_ty = ty: {
3838338452 if (body.len != 0) {
38384- _ = try sema.analyzeInlineBody(& block, body, inst);
38453+ _ = try sema.analyzeInlineBody(block, body, inst);
3838538454 }
3838638455
3838738456 if (tag_type_ref != .none) {
38388- const ty = try sema.resolveType(& block, tag_ty_src, tag_type_ref);
38457+ const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
3838938458 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {
38390- return sema.fail(& block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(pt)});
38459+ return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(pt)});
3839138460 }
3839238461 break :ty ty;
3839338462 } else if (fields_len == 0) {
@@ -38402,7 +38471,7 @@ pub fn resolveDeclaredEnum(
3840238471
3840338472 if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
3840438473 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) {
38405- return sema.fail(& block, src, "non-exhaustive enum specifies every value", .{});
38474+ return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});
3840638475 }
3840738476 }
3840838477
@@ -38434,7 +38503,7 @@ pub fn resolveDeclaredEnum(
3843438503 const tag_val_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
3843538504 extra_index += 1;
3843638505 const tag_inst = try sema.resolveInst(tag_val_ref);
38437- last_tag_val = try sema.resolveConstDefinedValue(& block, .{
38506+ last_tag_val = try sema.resolveConstDefinedValue(block, .{
3843838507 .base_node_inst = tracked_inst,
3843938508 .offset = .{ .container_field_name = field_i },
3844038509 }, tag_inst, .{ .simple = .enum_field_tag_value });
@@ -38447,12 +38516,12 @@ pub fn resolveDeclaredEnum(
3844738516 .offset = .{ .container_field_value = conflict.prev_field_idx },
3844838517 };
3844938518 const msg = msg: {
38450- const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, & sema)});
38519+ const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
3845138520 errdefer msg.destroy(gpa);
3845238521 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
3845338522 break :msg msg;
3845438523 };
38455- return sema.failWithOwnedErrorMsg(& block, msg);
38524+ return sema.failWithOwnedErrorMsg(block, msg);
3845638525 }
3845738526 break :overflow false;
3845838527 } else if (any_values) overflow: {
@@ -38469,12 +38538,12 @@ pub fn resolveDeclaredEnum(
3846938538 .offset = .{ .container_field_value = conflict.prev_field_idx },
3847038539 };
3847138540 const msg = msg: {
38472- const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, & sema)});
38541+ const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
3847338542 errdefer msg.destroy(gpa);
3847438543 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
3847538544 break :msg msg;
3847638545 };
38477- return sema.failWithOwnedErrorMsg(& block, msg);
38546+ return sema.failWithOwnedErrorMsg(block, msg);
3847838547 }
3847938548 break :overflow false;
3848038549 } else overflow: {
@@ -38487,9 +38556,9 @@ pub fn resolveDeclaredEnum(
3848738556
3848838557 if (tag_overflow) {
3848938558 const msg = try sema.errMsg(value_src, "enumeration value '{}' too large for type '{}'", .{
38490- last_tag_val.?.fmtValueSema(pt, & sema), int_tag_ty.fmt(pt),
38559+ last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),
3849138560 });
38492- return sema.failWithOwnedErrorMsg(& block, msg);
38561+ return sema.failWithOwnedErrorMsg(block, msg);
3849338562 }
3849438563 }
3849538564}
0 commit comments