-
Notifications
You must be signed in to change notification settings - Fork 3
some 0.16 api fixes #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,14 +36,18 @@ Always check local docs before web search. | |
|
|
||
| | Old (0.15.x) | New (0.16.0) | | ||
| |--------------|--------------| | ||
| | `@Type(.Int(...))` | `@Int(.signed, bits)` | | ||
| | `@Type(.Struct(...))` | `@Struct(layout, BackingInt, field_names, field_types, field_defaults, field_is_comptime, field_alignments)` | | ||
| | `@Type(.Pointer(...))` | `@Pointer(size, attrs, Element, sentinel)` | | ||
| | `@Type(.Fn(...))` | `@Fn(param_types, param_attrs, ReturnType, attrs)` | | ||
| | `@Type(.Tuple(...))` | `@Tuple(field_types)` | | ||
| | `@Type(.{ .int = ... })` | `@Int(signedness, bits)` | | ||
| | `@Type(.{ .@"struct" = ... })` | `@Struct(layout, BackingInt, field_names, field_types, field_attrs)` | | ||
| | `@Type(.{ .@"union" = ... })` | `@Union(layout, ArgType, field_names, field_types, field_attrs)` | | ||
| | `@Type(.{ .@"enum" = ... })` | `@Enum(TagType, exhaustivity, field_names, field_values)` | | ||
| | `@Type(.{ .pointer = ... })` | `@Pointer(size, attrs, Element, sentinel)` | | ||
| | `@Type(.{ .@"fn" = ... })` | `@Fn(param_types, param_attrs, ReturnType, attrs)` | | ||
| | `@Type(.{ .@"struct" = ... })` (tuple) | `@Tuple(field_types)` | | ||
| | `@Type(.enum_literal)` | `@EnumLiteral()` | | ||
| | `@cImport({...})` | `b.addTranslateC(...)` + `@import("c")` (deprecated) | | ||
| | `std.net` | `std.Io.net` | | ||
| | `std.ArrayList.init(allocator)` | `std.ArrayList.initCapacity(allocator, n)` | | ||
| | `std.ArrayList.init(allocator)` | `var l: std.ArrayList(T) = .empty;` + allocator per method | | ||
| | `std.heap.GeneralPurposeAllocator` | `std.heap.DebugAllocator(.{})` | | ||
| | `std.crypto.random` | `std.Io.randomSecure(io, buf)` | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- target lines ---'
sed -n '40,60p;195,212p' zig-0.16/SKILL.md
printf '%s\n' '--- related random references ---'
rg -n -C 3 'crypto\.random|randomSecure|io\.random' zig-0.16/SKILL.mdRepository: zigcc/skills Length of output: 4374 🏁 Script executed: #!/bin/bash
set -e
sed -n '40,60p;195,212p' zig-0.16/SKILL.md
rg -n -C 3 'crypto\.random|randomSecure|io\.random' zig-0.16/SKILL.mdRepository: zigcc/skills Length of output: 4319 🌐 Web query:
💡 Result: In Zig 0.16.0, released on April 14, 2026, the standard library underwent a major redesign that introduced "I/O as an Interface" [1][2][3]. This change overhauled how randomness, networking, and other blocking operations are handled by requiring an explicit std.Io instance [3][4]. Key changes to randomness and the Citations:
🏁 Script executed: #!/bin/bash
set -e
curl -L --fail --silent --show-error \
https://ziglang.org/download/0.16.0/release-notes.html |
rg -n -i -C 5 'crypto\.random|randomSecure|io\.random|entropy'Repository: zigcc/skills Length of output: 6806 Map
Proposed wording-| `std.crypto.random` | `std.Io.randomSecure(io, buf)` |
+| `std.crypto.random` | `io.random(&buf)` |🤖 Prompt for AI Agents |
||
| | `std.meta.intToEnum` | `std.enums.fromInt` | | ||
| | `std.fmt.FormatOptions` | `std.fmt.Options` | | ||
|
|
@@ -61,33 +65,42 @@ Always check local docs before web search. | |
|
|
||
| ### @Type Removed — Use Individual Builtins | ||
|
|
||
| `@Type` is gone. Replace with these builtins: | ||
| `@Type` is gone, replaced by **8** individual builtins. Containers use a | ||
| "struct of arrays" strategy: field names, field types and field *attributes* are | ||
| passed as three separate slices, so `&@splat(.{})` is the idiom for "default | ||
| attributes on every field". | ||
|
|
||
| ```zig | ||
| // Integer type | ||
| const MyInt = @Int(.signed, 32); | ||
|
|
||
| // Struct type | ||
| // Struct type — 5 arguments. Alignment, comptime-ness and default value | ||
| // all live inside `std.builtin.Type.StructField.Attributes`. | ||
| const MyStruct = @Struct( | ||
| .auto, // layout | ||
| null, // BackingInt (for packed) | ||
| &.{"x", "y"}, // field_names | ||
| &.{ i32, i32 }, // field_types | ||
| &.{ null, null },// field_defaults | ||
| &.{ false, false }, // field_is_comptime | ||
| &.{ null, null },// field_alignments | ||
| .auto, // layout | ||
| null, // BackingInt (only for packed) | ||
| &.{ "x", "y" }, // field_names | ||
| &.{ i32, i32 }, // field_types | ||
| &.{ // field_attrs | ||
| .{}, | ||
| .{ .default_value_ptr = &@as(i32, 7) }, | ||
| }, | ||
| ); | ||
|
|
||
| // Pointer type | ||
| const MyPtr = @Pointer(.one, .{ | ||
| .alignment = 8, | ||
| .address_space = .generic, | ||
| .is_const = false, | ||
| .is_volatile = false, | ||
| }, u8, null); | ||
| // Enum type — takes field *values*, not types. | ||
| const MyTag = @Enum(u32, .exhaustive, &.{ "foo", "bar" }, &.{ 0, 1 }); | ||
|
|
||
| // Union type — same shape as @Struct; 2nd arg is the tag type (or backing | ||
| // integer for `packed`). | ||
| const MyUnion = @Union(.auto, MyTag, &.{ "foo", "bar" }, &.{ i64, f64 }, &@splat(.{})); | ||
|
|
||
| // Pointer type — attribute field names mirror the pointer syntax keywords, | ||
| // so they need @"" quoting: .@"const", .@"volatile", .@"allowzero", | ||
| // .@"align", .@"addrspace". There is no `.alignment` / `.is_const`. | ||
| const MyPtr = @Pointer(.one, .{ .@"const" = true, .@"align" = 8 }, u8, null); | ||
|
|
||
| // Function type | ||
| const MyFn = @Fn(&.{i32, i32}, &.{.{}, .{}}, i32, .{}); | ||
| const MyFn = @Fn(&.{ i32, i32 }, &@splat(.{}), i32, .{}); | ||
|
|
||
| // Tuple type | ||
| const MyTuple = @Tuple(&.{ i32, bool }); | ||
|
|
@@ -96,6 +109,8 @@ const MyTuple = @Tuple(&.{ i32, bool }); | |
| const EnumLitType = @EnumLiteral(); | ||
| ``` | ||
|
|
||
| `@typeInfo` is unchanged — only the *construction* side moved. | ||
|
|
||
| ### @cImport Deprecated — Use Build System Translation | ||
|
|
||
| `@cImport` is deprecated. Use `addTranslateC` in `build.zig`: | ||
|
|
@@ -168,7 +183,7 @@ Then in Zig: `const c = @import("c");` | |
|
|
||
| - `std.time.milliTimestamp` removed. Use `std.time.Timer` or `std.Io.Clock.now(clock, io)` and compare `Timestamp.nanoseconds`. | ||
| - Random secure bytes: `std.Io.randomSecure(io, buf)`; no `std.crypto.random` or `std.posix.getrandom` convenience. | ||
| - `std.process.getEnvVarOwned` removed; use `std.c.getenv` and copy. | ||
| - `std.process.getEnvVarOwned` removed; environment access is non-global now — go through `init.environ_map` / `init.environ` from `main` (see below), not `std.c.getenv` (libc-only). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target context ---'
sed -n '165,200p' zig-0.16/SKILL.md
printf '%s\n' '--- repository references ---'
rg -n -C 3 'std\.process\.Init|environ_map|minimal\.environ|init\.environ' . --glob '!node_modules' --glob '!dist' --glob '!build' || true
printf '%s\n' '--- official release-note references ---'
curl -L --fail --silent --show-error \
https://ziglang.org/download/0.16.0/release-notes.html |
rg -n -C 4 'environ_map|minimal\.environ|Init\.Minimal|std\.process\.Init' || trueRepository: zigcc/skills Length of output: 16515 Use the correct environment field for each Use 🤖 Prompt for AI Agents |
||
| - `std.posix.exit` removed; use `std.process.exit`. | ||
|
|
||
| ### TLS Client Options | ||
|
|
@@ -177,8 +192,7 @@ Then in Zig: `const c = @import("c");` | |
|
|
||
| ### MemoryPool API Changes | ||
|
|
||
| - `std.heap.MemoryPool(T).initCapacity(allocator, n)` returns the pool. | ||
| - `create`/`destroy` now require allocator. No bare `init()` or zero-arg `deinit()`. | ||
| See [MemoryPool](#memorypool) under *Memory & Allocator Changes*. | ||
|
|
||
| ### Format Options | ||
|
|
||
|
|
@@ -189,7 +203,7 @@ Then in Zig: `const c = @import("c");` | |
|
|
||
| ### Randomness / Crypto | ||
|
|
||
| - `std.crypto.random` removed. Use an `std.Io` instance: `const io = std.Io.Threaded.global_single_threaded.ioBasic(); io.random(&buf);`. | ||
| - `std.crypto.random` removed. Use an `std.Io` instance: `const io = std.Io.Threaded.global_single_threaded.io(); io.random(&buf);` (the accessor is `io()`). For cryptographic material use `std.Io.randomSecure(io, &buf)` instead, which can fail with `error.EntropyUnavailable`. | ||
| - `Ed25519.KeyPair.generate` now requires an `io: std.Io` argument. | ||
|
|
||
| ### Enum Conversion | ||
|
|
@@ -199,8 +213,9 @@ Then in Zig: `const c = @import("c");` | |
|
|
||
| ### Fixed-Buffer Writers in Tests | ||
|
|
||
| - `std.io.fixedBufferStream` removed. For in-memory writes use `var w = std.Io.Writer.fixed(buf);` and read bytes with `std.Io.Writer.buffered(&w)`. | ||
| - `std.ArrayList` no longer has `.init(allocator)` shorthand; use `.initCapacity(allocator, n)`. | ||
| - `std.io.fixedBufferStream` removed. For in-memory writes use `var w: std.Io.Writer = .fixed(buf);` and read bytes back with `w.buffered()`. | ||
| - `Writer.fixed` / `Reader.fixed` return the interface **itself**, so call `w.print(...)` directly. Wrappers embed it under different field names — `File.Writer`/`File.Reader` use `.interface`, `Io.Writer.Allocating` uses `.writer`. Check the type before reaching for `.interface`. | ||
| - `std.ArrayList` no longer has `.init(allocator)` shorthand; construct with `.empty` (or `.initCapacity(allocator, n)`) and pass the allocator to each method. | ||
|
|
||
| ### Collections | ||
|
|
||
|
|
@@ -382,11 +397,15 @@ const contents = try std.Io.Dir.cwd().readFileAlloc(io, file_name, allocator, .l | |
| // OLD | ||
| const contents = try file.readToEndAlloc(allocator, 1234); | ||
|
|
||
| // NEW | ||
| var file_reader = file.reader(&.{}); | ||
| // NEW — reader(io, buffer): both arguments are required | ||
| var buf: [4096]u8 = undefined; | ||
| var file_reader = file.reader(io, &buf); | ||
| const contents = try file_reader.interface.allocRemaining(allocator, .limited(1234)); | ||
| ``` | ||
|
|
||
| `File.reader` / `File.writer` (and the `*Streaming` variants) all take | ||
| `(file, io, buffer)` in 0.16 — the old buffer-only form is gone. | ||
|
|
||
| ### setTimestamps | ||
|
|
||
| ```zig | ||
|
|
@@ -457,6 +476,10 @@ const preopens: std.process.Preopens = try .init(arena); | |
| ### Atomic / Temporary Files | ||
|
|
||
| `std.Io.File.Atomic` is the new API for atomic file writes and temporary files. | ||
| It is **created by `std.Io.Dir.createFileAtomic(io, sub_path, options)`** — there | ||
| is no `Atomic.init`. Finish with `replace(io)` (overwrite destination) or | ||
| `link(io)` (fail if it exists), matching the `.replace` option you passed; always | ||
| `deinit(io)` afterwards. There is no `commit`. | ||
|
|
||
| - Linux: integrates with `O_TMPFILE` when possible. | ||
| - New: `std.Io.File.hardLink` | ||
|
|
@@ -472,7 +495,28 @@ const preopens: std.process.Preopens = try .init(arena); | |
|
|
||
| ### ThreadSafe Allocator removed | ||
|
|
||
| `std.heap.ThreadSafe` is removed; use `ArenaAllocator` directly, or synchronize access manually. | ||
| `std.heap.ThreadSafeAllocator` is removed — wrapping an allocator in a mutex is | ||
| considered an anti-pattern now that thread safety is built into the allocators | ||
| themselves. Do **not** reach for `ArenaAllocator` as a blanket replacement: an | ||
| arena never frees individual allocations. Pick by use case: | ||
|
|
||
| | Need | Use | | ||
| |------|-----| | ||
| | Process/request-scoped bump allocation | `std.heap.ArenaAllocator` (lock-free, threadsafe) | | ||
| | General purpose, ReleaseFast + threads | `std.heap.smp_allocator` (process-wide singleton) | | ||
| | General purpose, leak/UAF detection | `std.heap.DebugAllocator(.{})` (`Config.thread_safe` defaults to `!single_threaded`) | | ||
|
Comment on lines
+498
to
+507
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: printf '%s\n' '--- target excerpt ---'
sed -n '490,512p' zig-0.16/SKILL.md
printf '%s\n' '--- allocator references ---'
rg -n -C 2 'ThreadSafeAllocator|smp_allocator|DebugAllocator|ArenaAllocator|thread.?safe|threadsafe' zig-0.16/SKILL.md
printf '%s\n' '--- repository Zig sources and version metadata ---'
git ls-files | rg '(^|/)(build\.zig|build\.zig\.zon|lib/std/heap|std/heap|release-notes|README)' | head -80
rg -n 'ThreadSafeAllocator|smp_allocator|DebugAllocator|Config\.thread_safe|ArenaAllocator' . --glob '!zig-0.16/SKILL.md' --glob '!node_modules/**' | head -120Repository: zigcc/skills Length of output: 4587 🌐 Web query:
💡 Result: In Zig 0.16.0, released on April 14, 2026, significant changes were made to the allocator landscape, primarily focused on improving performance and thread safety [1][2]. Key Changes: 1. std.heap.ThreadSafeAllocator Removed: This allocator, which previously wrapped other allocators in a mutex to provide thread safety, has been removed [3][4]. Using such wrappers is now considered an anti-pattern [4][5]. Developers are encouraged to use allocators that handle thread safety internally in a lock-free manner or to synchronize access manually [3][5]. 2. ArenaAllocator Improvements: std.heap.ArenaAllocator is now lock-free and thread-safe by default [3][4]. It no longer requires wrapping in a ThreadSafeAllocator and can provide comparable performance in single-threaded contexts and improved performance under contention compared to previous versions [3][4]. 3. SmpAllocator: std.heap.smp_allocator is a high-performance, general-purpose allocator specifically designed for multi-threaded machines [6]. It utilizes global state and is optimized for use in ReleaseFast builds [7]. 4. DebugAllocator: This remains a critical tool for safety, capable of detecting double-frees, use-after-free errors, and memory leaks [6]. It is configurable, and users can control its thread-safety features via its configuration struct [6][8]. In 0.16.0, it is common to see DebugAllocator used in Debug and ReleaseSafe builds, while SmpAllocator is used in ReleaseFast and ReleaseSmall builds for better performance [7]. These changes reflect Zig's move toward lock-free, intrinsic thread safety within the standard library's core allocators rather than relying on generic wrapper types [5]. Citations:
🏁 Script executed: set -eu
tmpdir="$(mktemp -d)"
curl -fsSL https://raw.githubusercontent.com/ziglang/zig/0.16.0/README.md >/dev/null 2>&1 || true
for url in \
https://raw.githubusercontent.com/ziglang/zig/0.16.0/lib/std/heap/arena_allocator.zig \
https://raw.githubusercontent.com/ziglang/zig/0.16.0/lib/std/heap/debug_allocator.zig \
https://raw.githubusercontent.com/ziglang/zig/0.16.0/lib/std/heap/smp_allocator.zig \
https://raw.githubusercontent.com/ziglang/zig/0.16.0/CHANGELOG.md \
https://ziglang.org/download/0.16.0/release-notes.html
do
name="$(basename "$url")"
curl -fsSL "$url" -o "$tmpdir/$name" || printf 'FETCH_FAILED %s\n' "$url"
done
printf '%s\n' '--- official release-note allocator references ---'
rg -n -i -C 3 'ThreadSafeAllocator|ArenaAllocator|smp_allocator|DebugAllocator|thread.?safe|allocator' "$tmpdir/release-notes.html" "$tmpdir/CHANGELOG.md" 2>/dev/null | head -240 || true
printf '%s\n' '--- arena allocator thread-safety implementation references ---'
rg -n -i -C 3 'thread|mutex|atomic|lock|sync|free' "$tmpdir/arena_allocator.zig" | head -180 || true
printf '%s\n' '--- debug allocator thread-safety implementation references ---'
rg -n -i -C 3 'thread_safe|thread|mutex|atomic|lock' "$tmpdir/debug_allocator.zig" | head -180 || true
printf '%s\n' '--- smp allocator thread-safety implementation references ---'
rg -n -i -C 3 'thread|mutex|atomic|lock|sync' "$tmpdir/smp_allocator.zig" | head -180 || trueRepository: zigcc/skills Length of output: 23500 Limit the allocator thread-safety claim.
🤖 Prompt for AI Agents |
||
| | Inside `main` | `init.gpa` — already threadsafe, with leak checking in Debug | | ||
|
|
||
| ### GeneralPurposeAllocator renamed | ||
|
|
||
| `std.heap.GeneralPurposeAllocator` no longer exists. It is `std.heap.DebugAllocator`, | ||
| constructed with the `.init` decl literal: | ||
|
|
||
| ```zig | ||
| var da: std.heap.DebugAllocator(.{}) = .init; | ||
| defer std.debug.assert(da.deinit() == .ok); // returns std.heap.Check | ||
| const gpa = da.allocator(); | ||
| ``` | ||
|
|
||
| ### Memory Locking / Protection moved to `std.process` | ||
|
|
||
|
|
@@ -500,9 +544,27 @@ std.posix.PROT.READ | std.posix.PROT.WRITE | |
|
|
||
| ### MemoryPool | ||
|
|
||
| - `std.heap.MemoryPool(T).initCapacity(allocator, n)` returns the pool. | ||
| - `create`/`destroy` now require allocator parameter. | ||
| - New unmanaged variants: `MemoryPoolUnmanaged`, `MemoryPoolAlignedUnmanaged`, `MemoryPoolExtraUnmanaged`. | ||
| `std.heap.MemoryPool(T)` **is now the unmanaged pool** — the naming convention | ||
| flipped, so there is no `MemoryPoolUnmanaged`. The managed variants moved to | ||
| `std.heap.memory_pool.Managed` / `.ExtraManaged` and are marked deprecated. | ||
| `std.heap.MemoryPoolAligned`, `MemoryPoolExtra` and `MemoryPoolOptions` are | ||
| deprecated aliases too — prefer `std.heap.memory_pool.Aligned` / `.Extra` / | ||
| `.Options`. | ||
|
|
||
| ```zig | ||
| var pool: std.heap.MemoryPool(u32) = .empty; // decl literal, no init() | ||
| defer pool.deinit(gpa); // deinit takes the allocator | ||
|
|
||
| try pool.addCapacity(gpa, 8); // optional pre-allocation | ||
| const p = try pool.create(gpa); // create DOES take the allocator | ||
| pool.destroy(p); // destroy does NOT | ||
| _ = pool.reset(gpa, .retain_capacity); | ||
| ``` | ||
|
|
||
| `initCapacity(allocator, n)` also exists as an alternative to `.empty` + | ||
| `addCapacity`. Note the asymmetry: only the allocating operations | ||
| (`initCapacity`, `addCapacity`, `create`, `deinit`, `reset`) take an | ||
| `Allocator`; `destroy` just pushes onto the free list. | ||
|
Comment on lines
+547
to
+567
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
zig version
lib_dir="$(zig env | python3 -c 'import json, sys; print(json.load(sys.stdin)["lib_dir"])')"
rg -n 'MemoryPool(Unmanaged|Aligned|Extra|Options)?|memory_pool' \
"$lib_dir/std"Repository: zigcc/skills Length of output: 191 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- repository files related to Zig 0.16 ---'
git ls-files | rg '(^|/)(zig-0\.16|.*zig.*0\.16|SKILL\.md$)' | head -200
printf '%s\n' '--- references to MemoryPool in the repository ---'
rg -n -C 3 'MemoryPool(Unmanaged|Aligned|Extra|Options)?|memory_pool' . \
-g '*.md' -g '*.zig' -g '*.json' -g '*.yml' -g '*.yaml' \
| head -400
printf '%s\n' '--- toolchain pins and Zig version references ---'
rg -n -i 'zig(version|lang)?|0\.16\.0|toolchain|release.notes|release-notes' . \
-g '!node_modules' -g '!dist' -g '!build' \
| head -400Repository: zigcc/skills Length of output: 19951 🌐 Web query:
💡 Result: In Zig 0.16.0, the memory pool API underwent significant changes to align with the language's shift toward unmanaged-style containers [1][2]. The core change is the introduction of unmanaged variants for memory pools, which do not store an internal Allocator, requiring the caller to pass an allocator to operations [1][3]. Key changes and usage in 0.16.0 include: 1. Unmanaged Variants: The new primary types are MemoryPoolUnmanaged, MemoryPoolAlignedUnmanaged, and MemoryPoolExtraUnmanaged [1][2]. These are located in std.heap.memory_pool [1]. 2. Managed Aliases: Existing MemoryPool types in std.heap now serve as managed wrappers (aliases) around these unmanaged versions [1][3]. These managed variants are marked as deprecated [1]. 3. API Signature Changes: Unlike the older managed versions, the unmanaged variants do not have an internal Allocator field [1][4]. Consequently, functions such as create and destroy now require an explicit Allocator parameter [2]. 4. Initialization: The unmanaged variants typically use.empty as a default initializer [1]. When capacity is needed, initCapacity is used instead of older preheating concepts [1][2]. Migration note: When updating code to Zig 0.16.0, you should transition to using the unmanaged variants directly and update your method calls to pass an Allocator explicitly [1][2]. Managed variants may still exist for backward compatibility but are deprecated [1]. Citations:
🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
urls=(
"https://ziglang.org/download/0.16.0/release-notes.html"
"https://raw.githubusercontent.com/ziglang/zig/0.16.0/lib/std/heap.zig"
"https://raw.githubusercontent.com/ziglang/zig/0.16.0/lib/std/heap/memory_pool.zig"
)
for url in "${urls[@]}"; do
printf '\n--- %s ---\n' "$url"
curl -LfsS --max-time 20 "$url" \
| rg -n -C 4 'MemoryPool(Unmanaged|Aligned|Extra|Options)?|memory_pool|unmanaged pool|managed pool' \
| head -200 || true
doneRepository: zigcc/skills Length of output: 1376 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- release-note context ---'
curl -LfsS --max-time 20 \
'https://ziglang.org/download/0.16.0/release-notes.html' \
| sed -n '3728,3775p'
printf '%s\n' '--- PR 23234 metadata and changed paths ---'
curl -LfsS --max-time 20 \
'https://api.github.com/repos/ziglang/zig/pulls/23234' \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(json.dumps({k:d.get(k) for k in ("state","title","merged_at","merge_commit_sha","html_url")}, indent=2))'
curl -LfsS --max-time 20 \
'https://api.github.com/repos/ziglang/zig/pulls/23234/files?per_page=100' \
| python3 -c 'import json,sys; print("\n".join(f"{x.get(\"status\")} {x.get(\"filename\")}" for x in json.load(sys.stdin)))'
printf '%s\n' '--- likely source locations in the PR diff ---'
curl -LfsS --max-time 20 \
'https://github.com/ziglang/zig/pull/23234.diff' \
| rg -n -C 5 'MemoryPool(Unmanaged|Aligned|Extra|Options)?|memory_pool|pub const MemoryPool' \
| head -300Repository: zigcc/skills Length of output: 4046 Use the correct Zig 0.16.0 The guide targets Zig 0.16.0, whose release notes add 🤖 Prompt for AI Agents |
||
|
|
||
| ### Io.Writer.Allocating alignment field | ||
|
|
||
|
|
@@ -567,7 +629,9 @@ var full = std.EnumSet(MyEnum).full; | |
| | Removed API | Replacement | | ||
| |-------------|-------------| | ||
| | `std.Thread.Pool` | `std.Io.Group`, `Io.async`, `Io.concurrent` | | ||
| | `std.heap.ThreadSafe` | `std.heap.ArenaAllocator` (now thread-safe) | | ||
| | `std.heap.ThreadSafeAllocator` | `std.heap.smp_allocator`, `DebugAllocator`, or `ArenaAllocator` (all threadsafe) | | ||
| | `std.heap.GeneralPurposeAllocator` | `std.heap.DebugAllocator(.{})` | | ||
| | `std.heap.MemoryPoolUnmanaged` (dev-only name, never shipped) | `std.heap.MemoryPool` (already unmanaged) | | ||
| | `std.io.fixedBufferStream` | `std.Io.Reader.fixed(data)` / `std.Io.Writer.fixed(buf)` | | ||
| | `std.Io.GenericReader` | `std.Io.Reader` | | ||
| | `std.Io.AnyReader` | `std.Io.Reader` | | ||
|
|
@@ -595,7 +659,7 @@ const std = @import("std"); | |
| pub fn main(init: std.process.Init) !void { | ||
| const gpa = init.gpa; | ||
|
|
||
| var list = try std.ArrayList(u8).initCapacity(gpa, 16); | ||
| var list: std.ArrayList(u8) = .empty; // or: try .initCapacity(gpa, 16) | ||
| defer list.deinit(gpa); | ||
|
|
||
| try list.append(gpa, 'a'); | ||
|
|
@@ -607,10 +671,14 @@ pub fn main(init: std.process.Init) !void { | |
| } | ||
| ``` | ||
|
|
||
| ### HashMap (Default / Unmanaged Style) | ||
| ### HashMap (Unmanaged Style) | ||
|
|
||
| Unlike the array hash maps, `std.StringHashMap` / `std.AutoHashMap` are **still | ||
| the managed variants** in 0.16 — they keep an embedded allocator and have no | ||
| `.empty`. For the allocator-per-call style use the `Unmanaged` names: | ||
|
|
||
| ```zig | ||
| var map = std.StringHashMap(u32).empty; | ||
| var map: std.StringHashMapUnmanaged(u32) = .empty; | ||
| defer map.deinit(gpa); | ||
|
|
||
| try map.put(gpa, "key", 42); | ||
|
|
@@ -626,23 +694,27 @@ pub fn main(init: std.process.Init) !void { | |
| // Direct streaming write | ||
| try std.Io.File.stdout().writeStreamingAll(io, "Hello, world!\n"); | ||
|
|
||
| // Or via writer interface | ||
| var stdout_writer = std.Io.File.stdout().writer(&.{}); | ||
| // Or via writer interface — writer(io, buffer); flush before returning | ||
| var buf: [1024]u8 = undefined; | ||
| var stdout_writer = std.Io.File.stdout().writer(io, &buf); | ||
| try stdout_writer.interface.print("value: {d}\n", .{42}); | ||
| try stdout_writer.interface.flush(); | ||
| } | ||
| ``` | ||
|
|
||
| ### Fixed-Buffer Reader / Writer | ||
|
|
||
| ```zig | ||
| // Reader from byte slice | ||
| var data = "line1\nline2\n"; | ||
| const data = "line1\nline2\n"; | ||
| var reader: std.Io.Reader = .fixed(data); | ||
| const line = try reader.takeDelimiterExclusive('\n'); | ||
|
|
||
| // Writer into a stack buffer | ||
| // Writer into a stack buffer — `.fixed` IS the Writer, no `.interface` hop | ||
| var buf: [256]u8 = undefined; | ||
| var writer: std.Io.Writer = .fixed(&buf); | ||
| try writer.interface.print("count: {d}", .{7}); | ||
| try writer.print("count: {d}", .{7}); | ||
| const written = writer.buffered(); // "count: 7" | ||
| ``` | ||
|
|
||
| ### File I/O | ||
|
|
@@ -652,10 +724,16 @@ try writer.interface.print("count: {d}", .{7}); | |
| const contents = try std.Io.Dir.cwd().readFileAlloc(io, "input.txt", gpa, .limited(1024 * 1024)); | ||
| defer gpa.free(contents); | ||
|
|
||
| // Write file atomically | ||
| var atomic = try std.Io.File.Atomic.init(io, gpa, "output.txt"); | ||
| try atomic.file_writer.interface.print("data: {s}\n", .{"hello"}); | ||
| try atomic.commit(io); | ||
| // Write file atomically: Dir.createFileAtomic -> write -> replace/link -> deinit | ||
| var af = try std.Io.Dir.cwd().createFileAtomic(io, "output.txt", .{ .replace = true }); | ||
| defer af.deinit(io); // always, even after a successful finish | ||
|
|
||
| var buf: [4096]u8 = undefined; | ||
| var aw = af.file.writer(io, &buf); | ||
| try aw.interface.print("data: {s}\n", .{"hello"}); | ||
| try aw.interface.flush(); | ||
|
|
||
| try af.replace(io); // or af.link(io) to fail if the destination exists | ||
| ``` | ||
|
|
||
| ### JSON | ||
|
|
@@ -707,12 +785,20 @@ test "basic arithmetic" { | |
|
|
||
| test "no leaks" { | ||
| const std = @import("std"); | ||
| var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||
| defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak"); | ||
| const allocator = gpa.allocator(); | ||
| // std.testing.allocator is already a leak-checking DebugAllocator. | ||
| const gpa = std.testing.allocator; | ||
| const ptr = try gpa.create(u32); | ||
| defer gpa.destroy(ptr); | ||
| } | ||
|
|
||
| test "explicit leak checking" { | ||
| const std = @import("std"); | ||
| var da: std.heap.DebugAllocator(.{}) = .init; | ||
| defer std.testing.expect(da.deinit() == .ok) catch @panic("leak"); | ||
| const gpa = da.allocator(); | ||
|
|
||
| const ptr = try allocator.create(u32); | ||
| defer allocator.destroy(ptr); | ||
| const ptr = try gpa.create(u32); | ||
| defer gpa.destroy(ptr); | ||
| } | ||
| ``` | ||
|
|
||
|
|
@@ -833,7 +919,7 @@ Notable additions: | |
| 3. **Add `fingerprint` and fix `name`** in `build.zig.zon`. | ||
| 4. **Thread `std.Io` through your app** — any function doing I/O, sleep, random, or time needs an `io` parameter. | ||
| 5. **Update `std.net` usages** to `std.Io.net` or raw syscalls. | ||
| 6. **Update `ArrayList` calls** to pass allocator explicitly and use `initCapacity`. | ||
| 6. **Update `ArrayList` calls** to construct with `.empty` and pass the allocator to every method. | ||
| 7. **Fix error set names** (CrossDevice, FileBusy, EnvironmentVariableMissing, DirNotEmpty). | ||
| 8. **Run `zig build test --test-timeout 500ms`** to catch hanging tests early. | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
sed -n '38,54p' zig-0.16/SKILL.mdRepository: zigcc/skills
Length of output: 1293
🌐 Web query:
Zig 0.16.0 release notes@cImportb.addTranslateC@import("c") deprecated💡 Result:
In Zig 0.16.0, the
@cImportlanguage builtin is deprecated and slated for future removal [1][2][3]. The recommended approach for C interoperability is now to handle C translation via the build system usingb.addTranslateC[1][4][5]. Key changes and migration details: 1. Deprecation: While@cImportremains available in 0.16.0, it is officially deprecated [1][6][3]. It has been moved out of the core language as part of a broader effort to reduce the compiler's coupling with libclang [7][5][8]. Note that in 0.16.0, the legacy@cImportimplementation was updated to be backed by the Aro C compiler instead of libclang [6][3]. 2. Build System Migration (b.addTranslateC): To replace@cImport, you should define a translation step in yourbuild.zigfile [1][3]. This involves creating a C header file that includes the necessary dependencies, usingb.addTranslateCto process it, and adding the resulting module to your executable or library [1][4][5]. Example migration pattern: // build.zig const translate_c = b.addTranslateC(.{.root_source_file = b.path("src/c.h"),.target = target,.optimize = optimize, }); const exe = b.addExecutable(.{.name = "your_project",.root_module = b.createModule(.{.root_source_file = b.path("src/main.zig"),.imports = &.{.{.name = "c",.module = translate_c.createModule, }, }, }), }); // In your Zig source code const c =@import("c"); 3. Future Direction: The long-term plan is to move C translation functionality out of the Zig compiler executable entirely, relying on external, official packages liketranslate-c[8][9]. Developers are encouraged to use the build system approach now to prepare for this transition [7][8].Citations:
@cImportto the build system ziglang/zig#20630Move the deprecation marker to
@cImport({...}).b.addTranslateC(...)with@import("c")is the replacement path.🤖 Prompt for AI Agents