- IR / Codegen: unannotated
let n = Box::unwrap(boxed)typesnasT(for exampleNode), not defaultint. Annotatedlet n: Node = ...already lowered correctly.
- Type checker:
resolve_type_namerewrites parserStructnames toEnuminside generic parameters (and other composite types).Result<int, MyError>fromstdlib/result.iontype-checks; previously expected and actual printed identically and failed.
- Codegen:
Box::unwrapcopies the payload out, then callsion_box_freeon the box pointer (it does not dropT). EveryBox::unwrapcall site previously leaked the heap allocation.
- IR / Codegen:
Box::new(StructLit)as a directletinitializer allocatessizeof(Struct)/Struct*(IR no longer types struct literals asint;Box::newprefers the let expected type likeVec::new).
- Type checker: recursive structs/enums no longer stack-overflow the compiler. Cycle-aware walks for no-escape,
Send,Eq, and drop analysis; bare value cycles (next: Node,next: Option<Node>) are rejected asInfiniteSize, whileBox/Vec/ raw-pointer indirection remains allowed (andBox<&T>still fails no-escape). - Codegen:
Box::newuses the argument's real type forsizeof/ pointer type (no longer alwaysint). MonomorphizedOption<Box<Struct>>is emitted before the struct body (with a struct forward decl) so recursive boxes produce valid C. - Docs: ION_SPEC §1.3 clarifies no self-referential borrows vs recursive owned types via indirection; skills and tests cover Send/Eq on recursive Box nodes.
- Type checker: matching
&UserGenericEnum<Concrete>substitutes type parameters into variant payload bindings (for exampleStatus::Ready(v)on&Status<int>bindsvasint, sov + 0type-checks). Previously the subst map only matched bareGeneric, leaving&T. - Type checker:
resolve_type_namerecurses into&Tso&Flagparameters resolveFlagas an enum (not a struct), matching&farguments. - Codegen: match on
&Enum/&GenericEnumderef-copies the scrutinee into a value temporary (Status_int x = *s,Flag x = *f), including when the param type still carries parserStruct("Flag")for an enum name. Live binding types keepVec::get_refcopy payloads from being double-dereferenced.
- Codegen: reborrowed non-copy struct fields passed to
&T/&mut Tparameters (for examplepeek(c.data, 0)withc: &Containeranddata: Vec<int>) emit&(c->data)so C pointer arity matchesVec_T**. Nested embedded paths use.after the first hop (&(w->inner.data)). Previously the bare field load (Vec_T*) compiled under default GCC flags and segfaulted at runtime.
- Parser:
if 5 < x { f(x); }(literal on the left of</<=, function call in the body) no longer misparses as a struct literal. Struct-vs-block lookahead after{requiresname:for fields, so calls likef(stay block statements.
- CLI:
ion-compiler --help/-hprints usage and exits 0 (aligned withion-build). - Parser: trailing
;after a statement-formmatchis optional (ION_SPECmatch_stmtneeds none; existingmatch { ... };still parses). Rvaluematchis unchanged. - Driver:
ion-compilerandion-buildreject programs with nofn mainafter merge (empty or helper-only entry files fail withMissingMaininstead of claiming a successful compile). - Diagnostics: invalid UTF-8 source fails at the file-read site with a clear path and byte offset (no Debug-formatted path noise).
- Docs: ION_SPEC §5.3 and skills clarify that scalar
&mutwrite-through is unsupported; mutate via&mut Structfields,&mutcallee parameters, or owner writes under the borrow checker.
- Builtins:
String::get(&String, int) -> Option<u8>(non-panicking byte peek) andSlice::get_ref(&[]T, int) -> Option<&T>(local borrow mirroringVec::get_ref, including array coercion).Sliceis a lexer keyword forSlice::qualification. Indexed writes on a root owner conflict with a liveget_refborrow. Spec, skills, LSP completions, TextMate grammar, and integration tests updated.
- Language / type checker: loop ownership uses structured reentry/exit edge snapshots (ION_SPEC §5.2). Move then
break/returnis allowed when there is no reentering path; after-loop state stays affine; exit-path disagreement errors at the loop join. Replaces the old "any move in a loop body" beta rule. Integration tests cover break/return/continue, while head-vs-break disagreement, and nested inner break.
- Fix: string literals passed directly to
String-typed call arguments now lower throughion_string_from_literal(same aslet s: String = "…"). Previously call sites could pass a raw C string (segfault or silent no-op). - Fix: extern call codegen restores
(uint8_t*)on string literals for*u8parameters when resolving types fromextern_functions(Linux CI-Werror=pointer-signon io/ffi tests). - Docs:
tests/README.mdnotes that release archives ship this catalog only, not the.ionharness files.
- Fix: method-call syntax on
&Vec<T>,&mut Vec<T>,&String, and&mut Stringparameters (missing dereference in cgen;String::lenrouted throughVec::lenin IR). - Fix:
examples/http_serverlinks on Linux/macOS (cflags_windowsfor Winsockclosemapping). - Tooling: GitHub Actions release workflow (multi-platform archives with docs/examples verification), Dependabot for pinned action SHAs.
- Docs:
ion-buildruntime/stdlib walk-up discovery;cflags_windows/cflags_unixinion.toml.
First tagged release of the Ion toolchain.
- Binaries:
ion-compiler,ion-build,ion-lsp(Cargo package version0.1.0) - Language: move-only ownership, no-escape borrows, channels/
spawn, generics,match,defer, FFI viaextern "C"/unsafe - Tooling:
ion.tomlproject builds, Linux and Windows CI, integration harness, VS Code/Cursor extension - Docs:
ION_SPEC.md,docs/BETA.md,docs/ABI.md,SECURITY.md - Status: First tagged
0.xrelease. See monthly sections below for the full history leading to this tag.
- VM-style idioms:
matchon&EnumfromVec::get_ref; struct field assignment and+=on owned/&mutpaths; method desugaring (vec.push,vec.get_ref) with correct borrows; nested generic types (Vec<Vec<int>>); match-arm control-flow unification (break/returnwith value arms);&strcall-site coercion; enum literals inVec::push/setwithout double-wrapped C;&mut Structfield access via->in codegen. Integration tests and examplesbytecode_vm, updatedshowcase,todo_demo,http_server,text_summary. Fix extern call typing so&Targuments match&Tparameters (no erroneous copy-type ref stripping). FixOption<T>match codegen to use the scrutinee type instead of the first registered monomorph. Former negative match-arm rvalue tests now pass as positive runs. - Trait bounds follow-up: ION_SPEC §4.8
Eqrow documents function pointers; integration testtest_trait_bound_eq_fn_ok; method-call signature help threads generic bounds throughfn_hover_doc. Fix IR generic monomorphization when the first type argument is a function identifier (identity(add_one)): infer fn-pointer types from program signatures so mangled instantiations are emitted and call sites use the correct name. Integration testtest_trait_bound_copy_fn_ok;examples/trait_boundsexercisesidentity(add_one).
- Readiness hardening: beta compatibility and runtime ABI documents, a lightweight security policy, CLI/
ion-buildmulti-error type diagnostics, sanitizer CI smoke (6 tests), and full integration harness-Wall -Wextra -Werroron Linux CI. Cgen warning-hygiene improvements (binding usage tracking and(void)silences, borrow/defer silences, string literal.data/uint8_t*casts, stringfor...inlength casts),Stringruntime data asuint8_t*, andCFLAGS/LDFLAGSsupport in the integration harness. - Language:
foriteration,matchguards,else if,break/continue,loop {},+=, hex/bin literals, function typesfn(T) -> R, tuple literals and destructuring. Capture-free fn literals (fn(T) -> Rlowered to static C function pointers;ClosureCapturefor outer bindings). - Stdlib & runtime:
fmt.ion,Result<T, E>,fs.read_to_string,String::push_byte. - Compiler: scope-drop codegen,
pthreadspawn, slice bounds checks, array-to-slice coercion, struct/enum field drops,Stringequality, module function name mangling, lasting-borrow rules (ION_SPEC 5.3), field-path borrow exclusivity, move/copy tracking fixes, generic monomorphization, generated C file banner (repo-relative source labels viaportable_source_label, GNU C note, merged stdlib note, multi-file provenance, comment-safe path escaping). - LSP: diagnostics, hover, completion, go-to-definition; multi-error reporting; symbol table mirroring; diagnostics cleared on close; hover fixes for
letbindings and module-qualified calls. Contiguous//doc comments attached to declarations (includingpubitems) for hover. - Tooling: GitHub Actions CI (Linux and Windows), pinned toolchain (1.96.0),
test_expectations.tsvmanifest,--version, line-numbered errors, Cursor agent skills. Splittcandcgeninto submodules.ion-builddriver andion.tomlmanifests (single/multi,out_dir,cflags,ldflags,stdlib_paths,emit_in_source); per-example manifests andbuild_hello/build_bad_mainharness smoke tests. Shareddiscover_import_configand stdlib search paths forion-compiler,ion-build, and LSP. Integration harness precompilesruntime/ion_runtime.conce per run (RUNTIME_OBJ).writing-ion-codeagent skill;creating-ion-skillsexamples index lists all eight project skills. Documented checked-inexamples/*.ccodegen snapshots in README and integration-test skill; regenerated example C output. Fixedresearching-pl-literatureskillpaper-seedsreference formatting. - Docs: README, CONTRIBUTING, ION_SPEC, and agent skills aligned on project layout,
ion-buildworkflow,emit_in_source, stdlib import order, LSP features and limitations,src/build/checklists, portable Git Bash paths fortest_runner.sh, and rebuilding release binaries before harness or example C regen (staletarget/release/ion-compilernote). - Fixes: match rvalue codegen,
Vecstruct drops, channel codegen, parser handling ofalias::call(), scope-drop for moved-into-call bindings, HTTP server on Windows, integration harness on Windows. Cgen return-unwind: stop marking bindings dropped after inner-branchreturn(restores outer-path drops), dedupe_-prefixed unused silences, mark call arguments moved at emission to avoid double-free on unwind, and unify all function returns viaemit_function_return(including diverging rvaluematcharms). Cgen struct field move-out neutralizes owned fields after partial move, deferred to statement end when the move is a call argument;Vec::pushpasses address of struct lvalues; non-generic enums emit before structs; tuple IR uses resolved element types andtuple_Vec_Tmangling with compound-zeroret_valfor tuple returns (functions and fn literals). Integer indexing andVec<i32>inference in the type checker. Match rvalue arms: reject diverging arms mixed with value arms; structural control-flow analysis for arm bodies (nestedif/else,loopwithoutbreak,unsafeblocks); reject mixed diverge and value-producing paths within one arm; cgen assigns throughif/elsevalue branches.fmt::int_to_stringusesString::push_byteper digit instead of per-digitpush_strbranches; integration test asserts0, negatives, andint::MIN.int::MIN/int::MAXon integer primitives;Vec::new()/with_capacity()inferTfrom alettype annotation. Clippy fix inportable_source_label.Vec::get/Vec::pop: IR infersOption<T>from the vector argument; cgen dereferences&mut Vec<T>parameters, unpacks runtimeOptionviaion_option_from_raw, and uses a temp for struct-returningVec::push/Vec::setcall values. Groupedmatchswitch arms: scope drops before the casebreak(GCC-Wimplicit-fallthroughunder-Werror); guarded arms in a shared variant case break inside the guardifso fallback arms do not run. Cgen: enum literals lower to compound initializers (no per-variant_newhelpers); unused bindings and parameters silenced with(void)at scope unwind instead of blanketION_MAYBE_UNUSED. Cgen monomorphization:Vec<T>/Option<T>typedefs mangle Ion type names (Vec_String, not C typedefs);match Vec::get/Vec::popresolvesOption<T>from return type or vector element type;String::push_strwith ownedStringreads source.data/.len. Integration teststest_vec_string_mangle,test_vec_get_multi_option,test_string_push_str_owned,test_vec_get_putback. ION_SPEC documentsVec::getmove-out and put-back scan.Vec::get_ref: stack-localOption<&T>for read-only vector peek; shared borrow on the vector owner; match arms bind&Tas a pointer (no by-value copy of struct elements with nested owned fields); IR records match pattern bindings for nested scans; integration teststest_vec_get_ref_*includingtest_vec_get_ref_scan_nested_vec.String::lencodegen: null-check theStringpointer, not&local(fixes GCC-Waddressunder CI-Werror). - Examples:
text_summary(fixture file),data_lib(multi-module),channel_worker(flat single-file),todo_demo(interactive stdin,Vecof structs withString). Per-example*.tomlmanifests forion-build.http_serveraccepts clients until stdinquit. - Multi-file fixes: merge private struct types for cross-module type checking; per-module C symbol prefixes in multi-file codegen (
io_print_int); walk-upruntime/discovery for nested build directories. Integration teststest_multi_struct,test_multi_fmt_io. Example policy: each demo underexamples/<name>/withion.toml; build output undertarget/only (no committed.c).
ion-lspand VS Code extension; go-to-definition. Runtime, tests, examples, and print lowering updates. Type-alias resolution in C prototypes.
- Initial compiler (lexer, parser, tc, IR, cgen), C runtime,
ION_SPEC.md, examples, integration tests,io/fsstdlib. Core language: ownership, borrows, channels,spawn, generics,match,defer, FFI.