authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-31 10:19:12+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:09+00:00
log38fdced8bb255d3460afefaacce9dc89dab97def
tree339ecf8e7e2243f137c53f130a0cd94129a4878a
parent650185692dc6fb6b9c2c4e591d37cb94410972e1
signaturelock-open Commit is signed but in an unrecognized format.

Sema: small cleanup


1 files changed, 60 insertions(+), 58 deletions(-)

src/Sema/type_resolution.zig+60-58
......@@ -493,65 +493,67 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
493493 };
494494 defer block.instructions.deinit(gpa);
495495
496 // MLUGG TODO: this is fucking ugly bro
497 const explicit_enum_tag_ty: ?Type = if (union_obj.is_reified) ty: {
498 break :ty switch (union_obj.enum_tag_mode) {
499 .explicit => .fromInterned(union_obj.enum_tag_type),
500 .auto => null,
501 };
502 } else ty: {
503 const zir_union = sema.code.getUnionDecl(zir_index);
504 if (zir_union.kind != .tagged_explicit) {
505 break :ty null; // enum tag type will be automatically generated
506 }
507 // Explicitly specified, so evaluate the enum tag type expression.
508 const tag_type_body = zir_union.arg_type_body.?;
509 const tag_type_src = block.src(.container_arg);
510 block.comptime_reason = .{ .reason = .{
511 .src = tag_type_src,
512 .r = .{ .simple = .union_enum_tag_type },
513 } };
514 const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index);
515 break :ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref);
516 };
517 const enum_tag_ty: Type = if (explicit_enum_tag_ty) |enum_tag_ty| ty: {
518 if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail(
519 &block,
520 block.src(.container_arg),
521 "expected enum tag type, found '{f}'",
522 .{enum_tag_ty.fmt(pt)},
523 );
524 break :ty enum_tag_ty;
525 } else switch (try ip.getGeneratedEnumTagType(gpa, io, pt.tid, .{
526 .union_type = union_ty.toIntern(),
527 // MLUGG TODO: a bit hacky icl
528 .int_tag_mode = mode: {
529 if (union_obj.is_reified) break :mode .auto;
530 const zir_union = sema.code.getUnionDecl(zir_index);
531 if (zir_union.kind != .tagged_enum_explicit) break :mode .auto;
532 break :mode .explicit;
496 const enum_tag_ty: Type = switch (union_obj.enum_tag_mode) {
497 .explicit => validated_tag_ty: {
498 // If the union is reified, its enum tag type is already populated. If the union is
499 // declared, we need to evaluate the enum tag type expression (the `E` in `union(E)`).
500 const tag_ty: Type = switch (union_obj.is_reified) {
501 true => .fromInterned(union_obj.enum_tag_type),
502 false => tag_ty: {
503 const zir_union = sema.code.getUnionDecl(zir_index);
504 assert(zir_union.kind == .tagged_explicit); // `Zcu.mapOldZirToNew` guarantees that the ZIR mapping preserves `kind`
505 const tag_type_body = zir_union.arg_type_body.?;
506 const tag_type_src = block.src(.container_arg);
507 block.comptime_reason = .{ .reason = .{
508 .src = tag_type_src,
509 .r = .{ .simple = .union_enum_tag_type },
510 } };
511 const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index);
512 break :tag_ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref);
513 },
514 };
515 // Because the type is explicitly specified, we need to validate it.
516 if (tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail(
517 &block,
518 block.src(.container_arg),
519 "expected enum tag type, found '{f}'",
520 .{tag_ty.fmt(pt)},
521 );
522 break :validated_tag_ty tag_ty;
533523 },
534 .fields_len = @intCast(union_obj.field_types.len),
535 })) {
536 .existing => |tag_ty| .fromInterned(tag_ty),
537 .wip => |wip| tag_ty: {
538 errdefer wip.cancel(ip, pt.tid);
539 _ = wip.setName(ip, try ip.getOrPutStringFmt(
540 gpa,
541 io,
542 pt.tid,
543 "@typeInfo({f}).@\"union\".tag_type.?",
544 .{union_obj.name.fmt(ip)},
545 .no_embedded_nulls,
546 ), .none);
547 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
548 .parent = union_obj.namespace.toOptional(),
549 .owner_type = wip.index,
550 .file_scope = zcu.namespacePtr(union_obj.namespace).file_scope,
551 .generation = zcu.generation,
552 });
553 if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
554 break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index));
524 // If no tag type was specified, we generate one keyed on this union type.
525 .auto => switch (try ip.getGeneratedEnumTagType(gpa, io, pt.tid, .{
526 .union_type = union_ty.toIntern(),
527 // The int tag for this enum is usually inferred---the exception is `union(enum(T))`.
528 .int_tag_mode = switch (union_obj.is_reified) {
529 true => .auto,
530 false => switch (sema.code.getUnionDecl(zir_index).kind) {
531 .tagged_enum_explicit => .auto,
532 else => .explicit,
533 },
534 },
535 .fields_len = @intCast(union_obj.field_types.len),
536 })) {
537 .existing => |tag_ty| .fromInterned(tag_ty),
538 .wip => |wip| tag_ty: {
539 errdefer wip.cancel(ip, pt.tid);
540 _ = wip.setName(ip, try ip.getOrPutStringFmt(
541 gpa,
542 io,
543 pt.tid,
544 "@typeInfo({f}).@\"union\".tag_type.?",
545 .{union_obj.name.fmt(ip)},
546 .no_embedded_nulls,
547 ), .none);
548 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
549 .parent = union_obj.namespace.toOptional(),
550 .owner_type = wip.index,
551 .file_scope = zcu.namespacePtr(union_obj.namespace).file_scope,
552 .generation = zcu.generation,
553 });
554 if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
555 break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index));
556 },
555557 },
556558 };
557559