Skip to content

fix(build): construct SQLITE_TRANSIENT without tripping Zig 0.16 pointer-alignment check#2

Merged
richardcase merged 1 commit into
mainfrom
fix-sqlite-transient-zig016
Jul 26, 2026
Merged

fix(build): construct SQLITE_TRANSIENT without tripping Zig 0.16 pointer-alignment check#2
richardcase merged 1 commit into
mainfrom
fix-sqlite-transient-zig016

Conversation

@richardcase

Copy link
Copy Markdown
Owner

Problem

zig build fails on aarch64 (Apple Silicon) while compiling src/sqlite.zig:

error: pointer type '?*const fn (?*anyopaque) callconv(.c) void' requires aligned address
    SQLITE_TRANSIENT = __helpers.cast(sqlite3_destructor_type, -@as(c_int, 1));

Zig 0.16's translate-c expands the SQLITE_TRANSIENT macro ((void(*)(void*))-1) to @ptrFromInt(-1) for the destructor's function-pointer type. On aarch64 function pointers are >1-aligned, so the comptime alignment check rejects the unaligned -1. (On x86_64 the original compiled, which is why Phase 2 built on Linux.)

Fix

Construct the sentinel against an align(1) function-pointer type — which accepts any address — and bind through a matching extern declaration of sqlite3_bind_text:

const SqliteDestructor = ?*align(1) const fn (?*anyopaque) callconv(.c) void;
const SQLITE_TRANSIENT: SqliteDestructor = @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))));
extern fn sqlite3_bind_text(stmt: ?*c.sqlite3_stmt, idx: c_int, text: [*c]const u8, n: c_int, destructor: SqliteDestructor) callconv(.c) c_int;

The destructor pointer is passed by value and never dereferenced, so this is ABI-safe and behaviorally identical to the C macro (SQLite receives the same (void*)-1 sentinel and copies the bound value). Single call site changed; works on both aarch64 and x86_64.

Verification (macOS / aarch64)

  • zig build ✅ (previously failed — this is the fix)
  • zig build test-cc_abi_test: PASS
  • zig build test-unit ✅ (exit 0)

Known separate issue (not addressed here)

zig build test-poll still fails to compile on macOS — but for an unrelated, pre-existing reason: the mock-server in tests/core/poll_test.zig hardcodes Linux socket types (std.os.linux.SOL/SO, sockaddr). Phase 2 was developed and validated on Linux, where test-poll passes; the test harness was never made portable to macOS. That's a test-harness portability bug, distinct from this build break, and best fixed separately (and validated on both platforms).

🤖 Generated with Claude Code

https://claude.ai/code/session_012tRqDtnoLYPka4TGZ1BwYe

…ter-alignment check

zig build failed on aarch64 (macOS) compiling src/sqlite.zig: translate-c
expands the SQLITE_TRANSIENT macro to @ptrFromInt(-1) for the destructor
function-pointer type, and Zig 0.16's comptime alignment check rejects it
because function pointers are >1-aligned on aarch64 and -1 is not aligned.

Construct the sentinel against an align(1) function-pointer type (which accepts
any address) and bind through a matching extern sqlite3_bind_text declaration.
The destructor pointer is passed by value and never dereferenced, so this is
ABI-safe and identical in behavior to the C macro. Works on both aarch64 and
x86_64 (where the original already compiled).

Verified on macOS/aarch64: zig build, zig build test-c, and zig build test-unit
all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012tRqDtnoLYPka4TGZ1BwYe
Signed-off-by: Richard Case <richard.case@outlook.com>
@richardcase
richardcase merged commit 0983881 into main Jul 26, 2026
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.

1 participant