<!-- verified-against: seed-llvm; examples: docs-examples-test -->

Translating C, Rust, and Zig constructions to seed

This is a construction guide, not a language scorecard. Translate the ownership invariant first, then choose the smallest Seed type that expresses it. The LLVM compiler is the authority for syntax and diagnostics.

Core translations

Intent C Rust Zig seed construction and invariant
owned text char * + manual free String allocated slice string; move it, clone explicitly, and return alloc_error on allocation failure
borrowed text const char * &str []const u8 str; provenance is checked and no free is required
owned bytes malloc/free buffer Vec<u8> ArrayList(u8) bytes; initialize through safe APIs and commit only initialized bytes
shared bytes ref-counted pointer by convention Arc<[u8]> shared owner by convention shared_bytes; clone the handle explicitly and never mutate the payload
fixed record struct struct struct struct; add @repr("c") only when the C ABI is the contract
optional pointer nullable pointer Option<NonNull<T>> optional pointer ?*mut T in unsafe code, or Option for a typed value
fallible result return code + out parameter Result<T,E> !T error union Result<T,E>; use ?, match, or an explicit boundary operation
cleanup guard goto cleanup Drop guard defer destructor plus structured cleanup; normal exits are exact-once
scoped scratch stack/manual arena arena or temporary owner arena allocator region(capacity) { ... }; values and views cannot escape
checked index caller-side bounds check slice[index] slice[index] values[index]; the compiler lowers a checked access
disjoint split pointer arithmetic + proof split_at_mut two slices by convention split_at_mut(index); the compiler records exclusive disjoint views
thread transfer mutex/channel convention Send/Sync thread-safe API convention spawn; send is required, and shared data also requires sync
task join result shared result slot JoinHandle<Result<...>> thread handle + result typed task result or fallible spawn; join before cleanup
C callback function pointer + void * extern "C" fn callconv(.C) fn named thin fn(...) -> ...; state travels in an explicit opaque handle
retained callback function pointer + context + destroy Box<dyn FnOnce>/FnMut owned closure/context box fn or boxed closure only inside Seed APIs; never pass it as a C pointer
atomic field _Atomic T Atomic* std.atomic raw atomic built-ins inside unsafe, wrapped by a narrow safe API
volatile MMIO volatile pointer access unsafe volatile API @volatile pointer access raw volatile operations in an explicit unsafe driver adapter
unchecked cast C cast unsafe transmute @ptrCast explicit unsafe address-space/pointer operation with a documented invariant

Translation procedure

  1. Identify who owns the allocation, handle, task, or foreign resource.
  2. Turn borrowed parameters into str, []T, or mut []T only when the backing owner is provably live for the call.
  3. Turn every implicit copy of an owned value into either a move or an explicit .clone().
  4. Turn error codes and cleanup branches into Result plus structured exits.
  5. Keep foreign layout in @repr("c") records and keep foreign calls inside unsafe wrappers with INSTALL.md requirements.
  6. Run seed check --deep, then seed build and seed test; diagnostics are evidence that the translated invariant is incomplete, not a reason to disable ownership.

Common non-translations