From c78dbf43422187c64dda4681d0e4b1e54a586ab2 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 16:31:39 +0000 Subject: [PATCH] Sema: expect 'alignment' fields in 'std.builtin.Type' to be '?usize' This is a language change which works nicely alongside some of the other changes in this branch. It will help to resolve the remaining couple of failures in the std and behavior tests. The actual std.builtin change is not in this commit, because we must update zig1.wasm first. --- src/Sema.zig | 98 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index a2662dbc67..337af02b7f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16250,11 +16250,6 @@ fn zirBuiltinSrc( return Air.internedToRef((try pt.aggregateValue(src_loc_ty, &fields)).toIntern()); } -/// MLUGG TODO: once this branch is in a more stable state, I need to make a language change so that -/// `std.builtin.Type` makes all `alignment` fields `?usize` instead of `comptime_int`, to prevent -/// explicit alignment annotations from sneaking in without the user requesting any; but doing that -/// right now would be really annoying because it would break the base compiler. I need to have the -/// compiler more-or-less fully migrated first. fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; @@ -16432,12 +16427,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }, .pointer => { const info = ty.ptrInfo(zcu); - const alignment_val = try pt.intValue(.comptime_int, bytes: { - if (info.flags.alignment.toByteUnits()) |b| break :bytes b; - const elem_ty: Type = .fromInterned(info.child); - try sema.ensureLayoutResolved(elem_ty, src, .type_info); - break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?; - }); + const alignment_ty = try pt.optionalType(.usize_type); + const alignment_val: Value = val: { + const bytes = info.flags.alignment.toByteUnits() orelse { + break :val try pt.nullValue(alignment_ty); + }; + const int_val = try pt.intValue(.usize, bytes); + break :val .fromInterned(try pt.intern(.{ .opt = .{ + .ty = alignment_ty.toIntern(), + .val = int_val.toIntern(), + } })); + }; const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); const pointer_ty = try sema.getBuiltinType(src, .@"Type.Pointer"); @@ -16450,7 +16450,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai Value.makeBool(info.flags.is_const).toIntern(), // is_volatile: bool, Value.makeBool(info.flags.is_volatile).toIntern(), - // alignment: comptime_int, + // alignment: ?usize, alignment_val.toIntern(), // address_space: AddressSpace (try pt.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(), @@ -16766,12 +16766,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const alignment = switch (layout) { - .auto, .@"extern" => switch (ty.explicitFieldAlignment(field_index, zcu)) { - .none => field_ty.abiAlignment(zcu), - else => |a| a, - }, - .@"packed" => .none, + const alignment_ty = try pt.optionalType(.usize_type); + const alignment_val: Value = val: { + const a: Alignment = switch (layout) { + .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), + .@"packed" => .none, + }; + const bytes = a.toByteUnits() orelse { + break :val try pt.nullValue(alignment_ty); + }; + const int_val = try pt.intValue(.usize, bytes); + break :val .fromInterned(try pt.intern(.{ .opt = .{ + .ty = alignment_ty.toIntern(), + .val = int_val.toIntern(), + } })); }; const union_field_fields = .{ @@ -16779,8 +16787,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai name_val, // type: type, field_ty.toIntern(), - // alignment: comptime_int, - (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), + // alignment: ?usize, + alignment_val.toIntern(), }; field_val.* = (try pt.aggregateValue(union_field_ty, &union_field_fields)).toIntern(); } @@ -16881,6 +16889,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const is_comptime = field_val != .none; const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null; const default_val_ptr = try sema.optRefValue(opt_default_val); + const struct_field_fields = .{ // name: [:0]const u8, name_val, @@ -16890,8 +16899,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai default_val_ptr.toIntern(), // is_comptime: bool, Value.makeBool(is_comptime).toIntern(), - // alignment: comptime_int, - (try pt.intValue(.comptime_int, Type.fromInterned(field_ty).abiAlignment(zcu).toByteUnits() orelse 0)).toIntern(), + // alignment: ?usize, + (try pt.nullValue(try pt.optionalType(.usize_type))).toIntern(), }; struct_field_val.* = (try pt.aggregateValue(struct_field_ty, &struct_field_fields)).toIntern(); } @@ -16937,12 +16946,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const opt_default_val: ?Value = if (field_default == .none) null else .fromInterned(field_default); const default_val_ptr = try sema.optRefValue(opt_default_val); - const alignment = switch (struct_type.layout) { - .auto, .@"extern" => switch (ty.explicitFieldAlignment(field_index, zcu)) { - .none => field_ty.defaultStructFieldAlignment(struct_type.layout, zcu), - else => |a| a, - }, - .@"packed" => .none, + + const alignment_ty = try pt.optionalType(.usize_type); + const alignment_val: Value = val: { + const a: Alignment = switch (struct_type.layout) { + .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), + .@"packed" => .none, + }; + const bytes = a.toByteUnits() orelse { + break :val try pt.nullValue(alignment_ty); + }; + const int_val = try pt.intValue(.usize, bytes); + break :val .fromInterned(try pt.intern(.{ .opt = .{ + .ty = alignment_ty.toIntern(), + .val = int_val.toIntern(), + } })); }; const struct_field_fields = .{ @@ -16954,8 +16972,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai default_val_ptr.toIntern(), // is_comptime: bool, Value.makeBool(field_is_comptime).toIntern(), - // alignment: comptime_int, - (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), + // alignment: ?usize, + alignment_val.toIntern(), }; field_val.* = (try pt.aggregateValue(struct_field_ty, &struct_field_fields)).toIntern(); } @@ -27425,7 +27443,7 @@ fn coerceExtra( const array_elem_ty = array_ty.childType(zcu); if (array_ty.arrayLen(zcu) != 1) break :single_item; const dest_is_mut = !dest_info.flags.is_const; - switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { + switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { .ok => {}, else => break :single_item, } @@ -27443,7 +27461,7 @@ fn coerceExtra( const dest_is_mut = !dest_info.flags.is_const; const dst_elem_type: Type = .fromInterned(dest_info.child); - const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val); + const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, null); switch (elem_res) { .ok => {}, else => { @@ -27504,7 +27522,7 @@ fn coerceExtra( const src_elem_ty = inst_ty.childType(zcu); const dest_is_mut = !dest_info.flags.is_const; const dst_elem_type: Type = .fromInterned(dest_info.child); - switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { + switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { .ok => {}, else => break :src_c_ptr, } @@ -27575,7 +27593,7 @@ fn coerceExtra( target, dest_ty_src, inst_src, - maybe_inst_val, + null, )) { .ok => {}, else => break :p, @@ -27646,7 +27664,7 @@ fn coerceExtra( target, dest_ty_src, inst_src, - maybe_inst_val, + null, )) { .ok => {}, else => break :p, @@ -27852,7 +27870,7 @@ fn coerceExtra( target, dest_ty_src, inst_src, - maybe_inst_val, + null, )) { break :array_to_array; } @@ -27931,7 +27949,7 @@ fn coerceExtra( // E!T to T if (inst_ty.zigTypeTag(zcu) == .error_union and - (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok) + (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, null)) == .ok) { try sema.errNote(inst_src, msg, "cannot convert error union to payload type", .{}); try sema.errNote(inst_src, msg, "consider using 'try', 'catch', or 'if'", .{}); @@ -27939,7 +27957,7 @@ fn coerceExtra( // ?T to T if (inst_ty.zigTypeTag(zcu) == .optional and - (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok) + (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, null)) == .ok) { try sema.errNote(inst_src, msg, "cannot convert optional to payload type", .{}); try sema.errNote(inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); @@ -28386,6 +28404,10 @@ pub fn coerceInMemoryAllowed( const pt = sema.pt; const zcu = pt.zcu; + if (src_val) |val| { + assert(val.typeOf(zcu).toIntern() == src_ty.toIntern()); + } + if (dest_ty.eql(src_ty, zcu)) return .ok;