Skip to content

feat: migrate to Zig 0.16 - #11

Closed
apotema wants to merge 5 commits into
mainfrom
feat/zig-0.16-migration
Closed

apotema wants to merge 5 commits into
mainfrom
feat/zig-0.16-migration

Conversation

@apotema

@apotema apotema commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bumps minimum_zig_version to 0.16.0
  • @Type(.{ .@"struct" }) → @Struct(...) in zon_coercion.zig (with StructField.Attributes reshaping)
  • std.testing.refAllDeclsRecursive → refAllDecls
  • Bumps zspec to apotema/zspec 0.16 branch

Status

  • zig build: ✅ PASS
  • zig build test: ✅ PASS

apotema and others added 2 commits May 14, 2026 08:51
Library source migrated to the new 0.16 APIs:
- @type(.{ .@"struct" }) → @struct(...)
- std.testing.refAllDeclsRecursive → refAllDecls

`zig build` passes. `zig build test` cannot run yet because the pinned
zspec dep is itself 0.16-incompatible (calls removed APIs in factory.zig
and runner.zig). Will be unblocked once zspec is migrated/republished.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Unblocks tests that previously failed due to zspec using removed 0.16
stdlib APIs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@apotema

apotema commented May 14, 2026

Copy link
Copy Markdown
Contributor Author

@copilot review

Copilot AI commented May 14, 2026

Copy link
Copy Markdown

@copilot review

Reviewed the current PR state at 2de40f9. I didn’t find any additional actionable issues from this pass, so no further code changes were needed.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the project to Zig 0.16.0, updating the minimum version and dependencies in build.zig.zon. In src/zon_coercion.zig, the MergedStructType function was refactored to use the new @Struct builtin and separate arrays for field metadata. Feedback for this refactor suggests optimizing the field lookup logic using std.meta.fieldInfo to avoid nested loops, preserving original field alignments instead of recalculating them, and using more idiomatic syntax for empty declarations in the @Struct call.

Comment thread src/zon_coercion.zig
Comment on lines +261 to +292
comptime var field_names: [field_count][]const u8 = undefined;
comptime var field_types: [field_count]type = undefined;
comptime var field_attrs: [field_count]std.builtin.Type.StructField.Attributes = undefined;
comptime var i = 0;

inline for (base_fields) |bf| {
if (@hasField(OverridesType, bf.name)) {
inline for (override_fields) |of| {
if (comptime std.mem.eql(u8, of.name, bf.name)) {
fields[i] = .{
.name = bf.name,
.type = of.type,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(of.type),
};
field_names[i] = bf.name;
field_types[i] = of.type;
field_attrs[i] = .{ .@"align" = @alignOf(of.type) };
}
}
} else {
fields[i] = .{
.name = bf.name,
.type = bf.type,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(bf.type),
};
field_names[i] = bf.name;
field_types[i] = bf.type;
field_attrs[i] = .{ .@"align" = @alignOf(bf.type) };
}
i += 1;
}

inline for (override_fields) |of| {
if (!@hasField(BaseType, of.name)) {
fields[i] = .{
.name = of.name,
.type = of.type,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(of.type),
};
field_names[i] = of.name;
field_types[i] = of.type;
field_attrs[i] = .{ .@"align" = @alignOf(of.type) };
i += 1;
}
}

return @Type(.{
.@"struct" = .{
.layout = .auto,
.fields = &fields,
.decls = &.{},
.is_tuple = false,
},
});
return @Struct(.auto, null, &field_names, &field_types, &field_attrs);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation of MergedStructType uses a nested inline for loop to find override types, resulting in $O(N \cdot M)$ complexity at comptime. This can be simplified and optimized using std.meta.fieldInfo to directly access field metadata by name. Additionally, using the actual alignment from the source fields (bf.alignment, of.alignment, or info.alignment) is preferred over forcing @alignOf(type) to ensure any custom alignment specified in the original types is preserved. Finally, for the @Struct call, passing &.{} instead of null for the declarations argument is more idiomatic for a struct with no declarations.

    comptime var field_names: [field_count][]const u8 = undefined;
    comptime var field_types: [field_count]type = undefined;
    comptime var field_attrs: [field_count]std.builtin.Type.StructField.Attributes = undefined;
    comptime var i = 0;

    inline for (base_fields) |bf| {
        field_names[i] = bf.name;
        if (@hasField(OverridesType, bf.name)) {
            const info = std.meta.fieldInfo(OverridesType, bf.name);
            field_types[i] = info.type;
            field_attrs[i] = .{ .@"align" = info.alignment };
        } else {
            field_types[i] = bf.type;
            field_attrs[i] = .{ .@"align" = bf.alignment };
        }
        i += 1;
    }

    inline for (override_fields) |of| {
        if (!@hasField(BaseType, of.name)) {
            field_names[i] = of.name;
            field_types[i] = of.type;
            field_attrs[i] = .{ .@"align" = of.alignment };
            i += 1;
        }
    }

    return @Struct(.auto, &.{}, &field_names, &field_types, &field_attrs);

@cursor

cursor Bot commented May 14, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Bumps the compiler/toolchain baseline to Zig 0.16 and updates dependent tooling/APIs, which can introduce build or comptime behavior differences across the project despite minimal logic changes.

Overview
Migrates the project to Zig 0.16 by bumping the CI toolchain and build.zig.zon minimum_zig_version, and updating the zspec dependency to v0.9.1.

Updates comptime struct-type construction in zon_coercion.zig from @Type(.{ .@"struct" = ... }) to the new @Struct(...) API (including StructField.Attributes handling), and adjusts tests to use std.testing.refAllDecls instead of refAllDeclsRecursive.

Reviewed by Cursor Bugbot for commit e441eb8. Bugbot is set up for automated code reviews on this repo. Configure here.

Zig 0.16 migration requires CI to run on 0.16.0 too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6ad88cb. Configure here.

Comment thread tests/root.zig

test {
std.testing.refAllDeclsRecursive(@This());
std.testing.refAllDecls(@This());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching to refAllDecls silently skips all nested tests

High Severity

Changing refAllDeclsRecursive to refAllDecls silently disables the entire test suite. Every test file uses zspec's nested-struct pattern (e.g., pub const AStarSpec = struct { pub const basic_pathfinding = struct { test "..." { … } } }), with zero top-level test blocks. refAllDecls only references the direct @import declarations without recursing into the nested structs, so the compiler never analyzes the inner test blocks. The zig build test passes vacuously — the single unnamed test in root.zig succeeds, but none of the actual test logic runs.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6ad88cb. Configure here.

apotema and others added 2 commits May 14, 2026 10:46
Zspec's 0.16 migration is now published as a tagged release.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
apotema added a commit that referenced this pull request May 14, 2026
Squashed from feat/zig-0.16-migration:
- e441eb8 chore: bump zspec to v0.9.1
- 4ef722d chore: bump zspec to v0.9.0 release
- 6ad88cb ci: bump Zig toolchain to 0.16.0 in workflows
- 2de40f9 chore: bump zspec to 0.16-compatible fork
- fa57583 feat: migrate to Zig 0.16 (partial — tests blocked by zspec dep)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@apotema apotema closed this May 14, 2026
@apotema
apotema deleted the feat/zig-0.16-migration branch May 14, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants