authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-04 16:33:51+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:38:50+00:00
log5ec3a0cd54351494dfc64a4d91f72a6020505c1d
treeb94a68372d6ea96cdabd020128b89a9c37374077
parent793fa93d9f99b49a6d91bd40195f5fcc783014d5
signaturelock-open Commit is signed but in an unrecognized format.

std: update for language changes

Now that zig1.wasm is updated, apply the matching standard library changes. The main one is in `std.builtin.Type`, where `alignment` fields now have type `?usize` rather than `comptime_int`. Additionally, we need to add explicit backing integers to some packed unions, because (due to https://github.com/ziglang/zig/issues/24714) they need explicit backing integers to be used in `extern` contexts. This change could not happen before now, because prior to this branch, packed unions did not allow explicit backing integer types (that is, this branch implemented https://github.com/ziglang/zig/issues/25350).

10 files changed, 82 insertions(+), 65 deletions(-)

lib/compiler/resinator/cvtres.zig+1-1
......@@ -410,7 +410,7 @@ pub const ResourceDirectoryTable = extern struct {
410410};
411411
412412pub const ResourceDirectoryEntry = extern struct {
413 entry: packed union {
413 entry: packed union(u32) {
414414 name_offset: packed struct(u32) {
415415 address: u31,
416416 /// This is undocumented in the PE/COFF spec, but the high bit
lib/std/builtin.zig+8-4
......@@ -592,8 +592,8 @@ pub const Type = union(enum) {
592592 size: Size,
593593 is_const: bool,
594594 is_volatile: bool,
595 /// TODO make this u16 instead of comptime_int
596 alignment: comptime_int,
595 /// `null` means implicit alignment, which is equivalent to `@alignOf(child)`.
596 alignment: ?usize,
597597 address_space: AddressSpace,
598598 child: type,
599599 is_allowzero: bool,
......@@ -670,7 +670,9 @@ pub const Type = union(enum) {
670670 /// See also: `defaultValue`.
671671 default_value_ptr: ?*const anyopaque,
672672 is_comptime: bool,
673 alignment: comptime_int,
673 /// `null` means the field alignment was not explicitly specified. The
674 /// field will still be aligned to at least `@alignOf` its `type`.
675 alignment: ?usize,
674676
675677 /// Loads the field's default value from `default_value_ptr`.
676678 /// Returns `null` if the field has no default value.
......@@ -747,7 +749,9 @@ pub const Type = union(enum) {
747749 pub const UnionField = struct {
748750 name: [:0]const u8,
749751 type: type,
750 alignment: comptime_int,
752 /// `null` means the field alignment was not explicitly specified. The
753 /// field will still be aligned to at least `@alignOf` its `type`.
754 alignment: ?usize,
751755
752756 /// This data structure is used by the Zig language code generation and
753757 /// therefore must be kept in sync with the compiler implementation.
lib/std/c/darwin.zig+1-1
......@@ -436,7 +436,7 @@ pub const thread_state_flavor_t = c_int;
436436pub const ipc_space_t = mach_port_t;
437437pub const ipc_space_port_t = ipc_space_t;
438438
439pub const mach_msg_option_t = packed union {
439pub const mach_msg_option_t = packed union(integer_t) {
440440 RCV: MACH.RCV,
441441 SEND: MACH.SEND,
442442
lib/std/c/darwin/dispatch.zig+1-1
......@@ -210,7 +210,7 @@ pub const source_timer_flags_t = packed struct(usize) {
210210 STRICT: bool = false,
211211 unused1: @Int(.unsigned, @bitSizeOf(usize) - 1) = 0,
212212};
213pub const source_flags_t = packed union {
213pub const source_flags_t = packed union(usize) {
214214 raw: usize,
215215 MACH_SEND: source_mach_send_flags_t,
216216 MACH_RECV: source_mach_recv_flags_t,
lib/std/macho.zig+1-1
......@@ -851,7 +851,7 @@ pub const nlist = extern struct {
851851
852852pub const nlist_64 = extern struct {
853853 n_strx: u32,
854 n_type: packed union {
854 n_type: packed union(u8) {
855855 bits: packed struct(u8) {
856856 ext: bool,
857857 type: enum(u3) {
lib/std/mem.zig+12-4
......@@ -38,6 +38,10 @@ pub const Alignment = enum(math.Log2Int(usize)) {
3838 return @enumFromInt(@ctz(n));
3939 }
4040
41 pub fn fromByteUnitsOptional(maybe_n: ?usize) ?Alignment {
42 return if (maybe_n) |n| .fromByteUnits(n) else null;
43 }
44
4145 pub inline fn of(comptime T: type) Alignment {
4246 return comptime fromByteUnits(@alignOf(T));
4347 }
......@@ -2287,8 +2291,8 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
22872291 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
22882292 } else inline for (std.meta.fields(S)) |f| {
22892293 switch (@typeInfo(f.type)) {
2290 .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)),
2291 .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)),
2294 .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)),
2295 .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)),
22922296 .@"enum" => {
22932297 @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name))));
22942298 },
......@@ -4330,7 +4334,7 @@ pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize {
43304334 @compileError("expected many item pointer, got " ++ @typeName(T));
43314335
43324336 // Do nothing if the pointer is already well-aligned.
4333 if (align_to <= info.pointer.alignment)
4337 if (align_to <= info.pointer.alignment orelse @alignOf(info.pointer.child))
43344338 return 0;
43354339
43364340 // Calculate the aligned base address with an eye out for overflow.
......@@ -4388,7 +4392,11 @@ fn CopyPtrAttrs(
43884392 .@"const" = ptr.is_const,
43894393 .@"volatile" = ptr.is_volatile,
43904394 .@"allowzero" = ptr.is_allowzero,
4391 .@"align" = ptr.alignment,
4395 .@"align" = ptr.alignment orelse a: {
4396 // If the new child is aligned differently than the old one, explicitly align the type.
4397 const want = @alignOf(ptr.child);
4398 break :a if (@alignOf(child) == want) null else want;
4399 },
43924400 .@"addrspace" = ptr.address_space,
43934401 }, child, null);
43944402}
lib/std/mem/Allocator.zig+52-47
......@@ -179,7 +179,11 @@ pub fn destroy(self: Allocator, ptr: anytype) void {
179179 const T = info.child;
180180 if (@sizeOf(T) == 0) return;
181181 const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr)));
182 self.rawFree(non_const_ptr[0..@sizeOf(T)], .fromByteUnits(info.alignment), @returnAddress());
182 self.rawFree(
183 non_const_ptr[0..@sizeOf(T)],
184 .fromByteUnits(info.alignment orelse @alignOf(T)),
185 @returnAddress(),
186 );
183187}
184188
185189/// Allocates an array of `n` items of type `T` and sets all the
......@@ -266,7 +270,7 @@ pub inline fn allocAdvancedWithRetAddr(
266270 n: usize,
267271 return_address: usize,
268272) Error![]align(if (alignment) |a| a.toByteUnits() else @alignOf(T)) T {
269 const a = comptime (alignment orelse Alignment.of(T));
273 const a: Alignment = alignment orelse comptime .of(T);
270274 const ptr: [*]align(a.toByteUnits()) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address));
271275 return ptr[0..n];
272276}
......@@ -278,7 +282,7 @@ fn allocWithSizeAndAlignment(
278282 n: usize,
279283 return_address: usize,
280284) Error![*]align(alignment.toByteUnits()) u8 {
281 const byte_count = math.mul(usize, size, n) catch return Error.OutOfMemory;
285 const byte_count = math.mul(usize, size, n) catch return error.OutOfMemory;
282286 return self.allocBytesWithAlignment(alignment, byte_count, return_address);
283287}
284288
......@@ -293,7 +297,7 @@ fn allocBytesWithAlignment(
293297 return @as([*]align(alignment.toByteUnits()) u8, @ptrFromInt(ptr));
294298 }
295299
296 const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return Error.OutOfMemory;
300 const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return error.OutOfMemory;
297301 @memset(byte_ptr[0..byte_count], undefined);
298302 return @alignCast(byte_ptr);
299303}
......@@ -308,9 +312,9 @@ fn allocBytesWithAlignment(
308312///
309313/// `new_len` may be zero, in which case the allocation is freed.
310314pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
311 const Slice = @typeInfo(@TypeOf(allocation)).pointer;
312 const T = Slice.child;
313 const alignment = Slice.alignment;
315 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
316 comptime assert(slice_info.size == .slice);
317 const T = slice_info.child;
314318 if (new_len == 0) {
315319 self.free(allocation);
316320 return true;
......@@ -323,7 +327,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
323327 // on WebAssembly: https://github.com/ziglang/zig/issues/9660
324328 //const new_len_bytes = new_len *| @sizeOf(T);
325329 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false;
326 return self.rawResize(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress());
330 return self.rawResize(
331 old_memory,
332 .fromByteUnits(slice_info.alignment orelse @alignOf(T)),
333 new_len_bytes,
334 @returnAddress(),
335 );
327336}
328337
329338/// Request to modify the size of an allocation, allowing relocation.
......@@ -342,14 +351,11 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
342351/// `new_len` may be zero, in which case the allocation is freed.
343352///
344353/// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
345pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
346 const Slice = @typeInfo(@TypeOf(allocation)).pointer;
347 break :t ?[]align(Slice.alignment) Slice.child;
348} {
349 const Slice = @typeInfo(@TypeOf(allocation)).pointer;
350 const T = Slice.child;
351
352 const alignment = Slice.alignment;
354pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) {
355 const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
356 comptime assert(slice_info.size == .slice);
357 const T = slice_info.child;
358
353359 if (new_len == 0) {
354360 self.free(allocation);
355361 return allocation[0..0];
......@@ -367,9 +373,13 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
367373 // on WebAssembly: https://github.com/ziglang/zig/issues/9660
368374 //const new_len_bytes = new_len *| @sizeOf(T);
369375 const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null;
370 const new_ptr = self.rawRemap(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()) orelse return null;
371 const new_memory: []align(alignment) u8 = @alignCast(new_ptr[0..new_len_bytes]);
372 return mem.bytesAsSlice(T, new_memory);
376 const new_ptr = self.rawRemap(
377 old_memory,
378 .fromByteUnits(slice_info.alignment orelse @alignOf(T)),
379 new_len_bytes,
380 @returnAddress(),
381 ) orelse return null;
382 return @ptrCast(@alignCast(new_ptr[0..new_len_bytes]));
373383}
374384
375385/// This function requests a new size for an existing allocation, which
......@@ -386,10 +396,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
386396/// do the realloc more efficiently than the caller
387397/// * `resize` which returns `false` when the `Allocator` implementation cannot
388398/// change the size without relocating the allocation.
389pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: {
390 const Slice = @typeInfo(@TypeOf(old_mem)).pointer;
391 break :t Error![]align(Slice.alignment) Slice.child;
392} {
399pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) {
393400 return self.reallocAdvanced(old_mem, new_n, @returnAddress());
394401}
395402
......@@ -398,51 +405,49 @@ pub fn reallocAdvanced(
398405 old_mem: anytype,
399406 new_n: usize,
400407 return_address: usize,
401) t: {
402 const Slice = @typeInfo(@TypeOf(old_mem)).pointer;
403 break :t Error![]align(Slice.alignment) Slice.child;
404} {
405 const Slice = @typeInfo(@TypeOf(old_mem)).pointer;
406 const T = Slice.child;
408) Error!@TypeOf(old_mem) {
409 const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
410 comptime assert(slice_info.size == .slice);
411 const T = slice_info.child;
407412 if (old_mem.len == 0) {
408 return self.allocAdvancedWithRetAddr(T, .fromByteUnits(Slice.alignment), new_n, return_address);
413 return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.alignment), new_n, return_address);
409414 }
410415 if (new_n == 0) {
411416 self.free(old_mem);
412 const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), Slice.alignment);
413 return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0];
417 const alignment = slice_info.alignment orelse @alignOf(T);
418 const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment);
419 const ptr: *align(alignment) [0]T = @ptrFromInt(addr);
420 return ptr;
414421 }
415422
416423 const old_byte_slice = mem.sliceAsBytes(old_mem);
417 const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
424 const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory;
418425 // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
419 if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| {
420 const new_bytes: []align(Slice.alignment) u8 = @alignCast(p[0..byte_count]);
421 return mem.bytesAsSlice(T, new_bytes);
426 if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), byte_count, return_address)) |p| {
427 return @ptrCast(@alignCast(p[0..byte_count]));
422428 }
423429
424 const new_mem = self.rawAlloc(byte_count, .fromByteUnits(Slice.alignment), return_address) orelse
430 const new_mem = self.rawAlloc(byte_count, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address) orelse
425431 return error.OutOfMemory;
426432 const copy_len = @min(byte_count, old_byte_slice.len);
427433 @memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]);
428434 @memset(old_byte_slice, undefined);
429 self.rawFree(old_byte_slice, .fromByteUnits(Slice.alignment), return_address);
435 self.rawFree(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address);
430436
431 const new_bytes: []align(Slice.alignment) u8 = @alignCast(new_mem[0..byte_count]);
432 return mem.bytesAsSlice(T, new_bytes);
437 return @ptrCast(@alignCast(new_mem[0..byte_count]));
433438}
434439
435440/// Free an array allocated with `alloc`.
436441/// If memory has length 0, free is a no-op.
437442/// To free a single item, see `destroy`.
438443pub fn free(self: Allocator, memory: anytype) void {
439 const Slice = @typeInfo(@TypeOf(memory)).pointer;
440 const bytes = mem.sliceAsBytes(memory);
441 const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0;
442 if (bytes_len == 0) return;
443 const non_const_ptr = @constCast(bytes.ptr);
444 @memset(non_const_ptr[0..bytes_len], undefined);
445 self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress());
444 const slice_info = @typeInfo(@TypeOf(memory)).pointer;
445 comptime assert(slice_info.size == .slice);
446 const mem_with_sent = memory[0 .. memory.len + @intFromBool(slice_info.sentinel() != null)];
447 const bytes: []u8 = @ptrCast(@constCast(mem_with_sent));
448 if (bytes.len == 0) return;
449 @memset(bytes, undefined);
450 self.rawFree(bytes, .fromByteUnits(slice_info.alignment orelse @alignOf(slice_info.child)), @returnAddress());
446451}
447452
448453/// Copies `m` to newly allocated memory. Caller owns the memory.
lib/std/meta.zig+1-1
......@@ -63,7 +63,7 @@ pub fn alignment(comptime T: type) comptime_int {
6363 .pointer, .@"fn" => alignment(info.child),
6464 else => @alignOf(T),
6565 },
66 .pointer => |info| info.alignment,
66 .pointer => |info| info.alignment orelse @alignOf(info.child),
6767 else => @alignOf(T),
6868 };
6969}
lib/std/multi_array_list.zig+2-2
......@@ -194,9 +194,9 @@ pub fn MultiArrayList(comptime T: type) type {
194194 data[i] = .{
195195 .size = @sizeOf(field_info.type),
196196 .size_index = i,
197 .alignment = if (@sizeOf(field_info.type) == 0) 1 else field_info.alignment,
197 .alignment = field_info.alignment orelse @alignOf(field_info.type),
198198 };
199 big_align = @max(big_align, @alignOf(field_info.type));
199 big_align = @max(big_align, data[i].alignment);
200200 }
201201 const Sort = struct {
202202 fn lessThan(context: void, lhs: Data, rhs: Data) bool {
lib/std/zon/parse.zig+3-3
......@@ -591,7 +591,7 @@ const Parser = struct {
591591 if (pointer.child == u8 and
592592 pointer.is_const and
593593 (pointer.sentinel() == null or pointer.sentinel() == 0) and
594 pointer.alignment == 1)
594 (pointer.alignment == null or pointer.alignment == 1))
595595 {
596596 if (opt) {
597597 return self.failNode(node, "expected optional string");
......@@ -717,7 +717,7 @@ const Parser = struct {
717717 pointer.size != .slice or
718718 !pointer.is_const or
719719 (pointer.sentinel() != null and pointer.sentinel() != 0) or
720 pointer.alignment != 1)
720 (pointer.alignment != null and pointer.alignment != 1))
721721 {
722722 return error.WrongType;
723723 }
......@@ -742,7 +742,7 @@ const Parser = struct {
742742 const slice = try self.gpa.allocWithOptions(
743743 pointer.child,
744744 nodes.len,
745 .fromByteUnits(pointer.alignment),
745 .fromByteUnitsOptional(pointer.alignment),
746746 pointer.sentinel(),
747747 );
748748 errdefer self.gpa.free(slice);