Releases: jasisz/aver
Aver 0.24.1
Patch release on top of "Divide" — a correctness fix in the optimizer and broader aver check hints.
Fixed
- Constant folding no longer drops a side effect or a non-terminating computation. When the optimizer collapsed a
match/Result.withDefault/?over a statically-knownResult/Option, or anInt.div/Int.modby a literal zero, it could discard a sub-expression that still had to run — silently dropping its effects (e.g. aConsole.print), or turning a program that should loop forever into one that returns; one wildcard case could also crash the VM. Folded expressions now always run their effects, in source order.
Changed
aver checkflags more redundant work — a loop invariant built directly inside a recursive call's arguments, and a pure function computed more than once with the same arguments in a single expression.
Aver 0.24.0 "Divide"
One middle-end under every backend; the last operator that could crash is now a function.
Breaking
- Integer
/is removed; useInt.div(a, b) : Result<Int, String>. It was the last partial operation posing as a total operator.a / bon twoInts is now a type error pointing atInt.div, which returnsResult.Erron a zero divisor or thei64::MIN / -1overflow.Int.divis Euclidean — the partner ofInt.mod(Int.div(-7, 2) == -4). Float/stays total. Migration:match Int.div(a, b), orResult.withDefault(Int.div(a, b), <fallback>)when the divisor is known non-zero.
Added
aver compile --emit-ir-after=mirdumps the textualMirProgram— the executable middle-end the VM runs, after HIR → MIR lowering and the optimize pipeline.aver compile --explain-mir-coveragereports how much of a program lowers to MIR (per function, with the dominant blocker);--target wasm-gcretargets the meter at the wasm-gc backend's reach.
Changed
Fn(...)is allowed only as a function-parameter type. Aver has no closures, so a function value can only be a named fn / builtin / constructor passed as an argument. UsingFn(...)as a return type, a field, a collection element, or a local binding is now a type error — keeping the concrete callee (and its effects) statically known at every call. To choose between functions dynamically, branch at the call site or model the choice as a sum type.
Fixed
- wasm-gc: a tuple binding that follows
_is no longer dropped.match pair { (_, value) -> value }returned the field's zero default instead of the bound element; tuple fields are now paired with their binding by position regardless of where the wildcards sit. aver run --self-hostkeeps pace with the language. The self-hosted interpreter now handlesInt.div, float literals inside string interpolation, and Unit-returningmainunder record/replay — three places it had lagged the VM. (Higher-order functions and multi-module programs are still being brought across.)
Compiler internals
- MIR is now the only runtime middle-end. The VM compiles exclusively through Core MIR (
src/ir/mir/); the old ~2200-line HIR tree-walking compiler is gone — a function that can't lower to MIR is a hard error, not a silent second path. wasm-gc and wasip2 emit from MIR too (resolved-HIR fallback for shapes they don't yet cover) and run the sharedir::mir::optimize()passes, so one optimizer improves every backend at once. - Owned
Vector/Mapare mutated in place. The MIR last-use pass updates a uniquely-held collection without copying it first, turning build-and-fill loops from O(n²) into O(n) — roughly 20× faster on the VM and 26× on native (--target rust) versus 0.23; wasm-gc is unchanged (it leans on the engine's GC). matchonInt.div/Int.mod'sResultlowers on every backend. The directly-consumed (boxed) form now builds theResult<Int, String>on wasm-gc and exports faithfully to Lean/Dafny (guarding the zero divisor so theErrarm is reachable), so the Ok/Err idiom is no longer VM-only.- A constant divisor compiles
Int.div/Int.moddown to bare division. The MIR const-folder rewritesInt.div(a, k)for a literalk ∉ {0, -1}toResult.Ok(a div_euclid k), then folds the consumer (withDefault/match) over the now-literal constructor — somatch Int.div(a, 10) { Ok / Err }andResult.withDefault(Int.div(a, 10), d)lower to a plain Euclidean division on every backend. The explicitResult-returning function disappears when it provably can't fail. - wasm-gc modules are byte-reproducible across builds. Carrier type slots are now registered in sorted order instead of
HashMap-iteration order.
Aver 0.23.0 "Shape"
What
aver shapesees,aver proofnow uses.
Breaking
- All commands now use the same module-root default: explicit
--module-rootwins, otherwise current working directory. Previouslyaver run,aver run --wasm-gc, andaver run --wasip2walked the entry file's parent chain to find a directory where everydepends [...]resolved, whileaver verify/aver check/aver context/aver compilealready used cwd. After this change, every command treats the same arguments the same way. Migration: if you relied onaver run projects/foo/main.avfrom the repo root findingprojects/foo/depends/*, add--module-root projects/foo(orcdinto that directory).
aver shape
- MVP — architectural smell radar (CLI + LSP). Per-fn archetypes (14 labels),
ModuleShape5-dim vector with derivedKind(ServiceClient,Orchestration,SmartConstructor,DataModule,PureHelpers,Library,EffectfulLibrary,EffectfulShell), and a histogram-based Layer guess (Domain/Parse/Command/AiStrategy/RenderUi/Infra) with confidence and runners-up.aver shape <dir>walks corpora;--lintchecksaver.toml's[[shape.expected]]. LSP surfaces the verdict via CodeLens, hover, and document symbol. - Module patterns are now first-class typed facts. Five shapes by name:
RefinementSmartConstructor,WrapperOverRecursion,ResultPipelineChain,RendererFormatter,MatchDispatcherFold. Surfaced in a newModule patterns:section in the CLI output and as apatternsarray in--json. Same data feeds the LSP andproof_lower. - Output is flat + colored — section headers at column 0, ANSI palette (bold headers, cyan Kind / Layer, yellow counts, magenta pattern variants). Auto-disables on non-TTY pipes;
NO_COLORrespected.
Proof export
- Three new
ProofStrategyvariants close universal laws on Lean and Dafny. Each consumes aModulePattern:WrapperOverRecursion— monoidal-accumulator wrapper (sum(xs) == sumDirect(xs)). Demo:examples/data/sum_acc.av.ResultPipelineChain—?-chain ≡ nestedmatch Result.Err -> Err. Demo:examples/core/result_chain.av.MatchDispatcherFold— two list folds equal by structural induction. Demo:examples/data/list_length_fold.av.
Tooling
aver proof --checkruns the backend verifier and gates regressions.--error-budget=N(Dafny) and--sorry-budget=N(Lean) tolerate up to N residual failures so CI can pin a budget;--check-jsonemits{backend, errors|sorries, budget, passed}for external harnesses. Exit codes: 0 within budget, 1 over, 2 on harness failure.- Playground Audit panel gains a Shape section — Kind · Layer summary; expand to see module-shape vector, histogram, recognized patterns, and per-fn archetypes. Same payload as
aver shape --json; no new toolbar button. aver verify --hostile: opaque runtime handles can be fabricated inside verify-trace context for system-handle effects (today:Tcp.Connection), so Oracle stubs can feed a deterministic conn into the SUT without round-tripping throughTcp.connect. Opt-in per type — user-defined opaques (Refinement.Natural, …) stay protected.examples/services/redis.avexercises this viaverify ping/set/get traceblocks.
Aver 0.22.1
Hardening
aver verifyworks on multi-module programs. 0.22.0 shipped with a regression: runningaver verify <entry>on any program that declareddepends [...]failed with"missing VM symbol for exposed function Foo.Bar.baz". Every multi-module example underexamples/refinement/(including the refinement-via-opaque flagship that Lift introduced),examples/apps/notepad/, andprojects/payment_ops/hit it;aver run,aver compile, andaver verify --wasm-gcwere unaffected. The VM verify path now loads dep modules the same way the other paths already do (both the disk-loader CLI shape and the pre-loaded playground/LSP shape).
Aver 0.22.0 "Lift"
Aver source stays ordinary. The proof export lifts it to the backend's native mathematical shape — refinements become subtypes, mutual recursion becomes a structural block, every verify-law passes through one classifier, and Dafny closes more obligations on its own.
Refinement recovery
- Aver recovers proof-language refinements from ordinary validated code. A single-field
Intrecord with a validating smart constructor (e.g.Natural { v: Int }withv >= 0) now exports as a native subtype on Lean ({ v : Int // P v }) and subset type on Dafny (type X = v: int | P v witness W); the predicate travels with the type. A public function that guardsn >= 0before calling a private worker similarly refines that worker's domain in the export. Universal laws likeadd_commutative(a: Natural, b: Natural)close in the backend's natural proof shape, no per-law tactic plumbing. Conservative and source-compatible — no new Aver annotation, andwhenclauses stronger than the recovered invariant are kept as theorem premises rather than silently dropped. Recovered refinements survive module boundaries.
Mutual recursion in proof export
- Mutual-recursion SCCs over
List/Vector/Stringparameters export natively. Lean emits a singlemutual ... termination_by ... endblock keyed off the structural measure; Dafny emits adecreases <measure>, <rank>tuple per member. The fuel-bounded helper-and-wrapper indirection is gone for these groups. Bounded-∀ universal laws over the SCC verify as real proofs (BigInt'sadd_commutativemoves fromassume {:axiom}on trust to a real theorem). Sample assertions no longer exhaust Lean's synth budget on compound predicates.
Law strategy substrate
- Both proof backends read every verify-law strategy from one classifier. Each
verify <fn> lawlowers to one of fourteen algebraic shapes (commutative / associative / identity / induction / library axiom / map update / linear arithmetic / four spec-equivalence flavours / linear recurrence) before Lean or Dafny emits anything. Visible viaaver compile --emit-ir-after law_lower. Effectful impl-vs-spec laws classify on the canonical post-Oracle-Lift shape;fib(n) == fibSpec(n)closes as a real proof on both backends (Nat-helper bridge + worker-shift lemma) where prior releases emittedsorry/ empty-body.
Dafny verifier improvements
dafny verifycloses 25 more proofs across the flagship suite (160 errors → 135). Smarterinfer_decreasespicks the actually-moving recursion measure across self-call sites (catchesrepeat(char_, n - 1)andscanExpTail(s, pos + 1, start)). List-induction hints case-split|xs| == 0and recurse onxs[1..], detecting recursive fns nested underMap.*/Option.*helpers.examples/data/map.avverifies clean;fibonacci,rle,quicksort,json,grok_s_languageall improve without regression.String.slicelowers via a clamp-to-empty helper instead of raws[from..to]. Aver's runtime semantics — negative or out-of-range indices collapse to an empty slice — now travel into the Dafny export.examples/data/date.avverifies clean (theparseIntSlice(s, from, to)shape no longer leaves uncloseable range obligations on every caller);examples/data/json.avcloses 24 more proofs at the same time (113 → 89 errors), entirely from the parser's slice-heavy lookahead. Source-compatible — no Aver-side change, the helper is emitted only whenString.sliceactually appears.- Float
/lowers via aFloatDivhelper that mirrors Aver's IEEE-754 semantics. Aver float division never crashes —1.0/0.0isInfinity,0.0/0.0isNaN. Dafny's exact-rationalreal, in contrast, makesa / bimposeb != 0on every caller. The new helper returns a defined value (0.0) when the divisor is zero, so callers likegoldenApprox(n) = Float.fromInt(fib(n + 1)) / Float.fromInt(fib(n))no longer need to provefib(n) ≥ 1just to compute the ratio.examples/data/fibonacci.avverifies clean. - Negative-domain guard recognition broader. Recursive
Intfunctions whose author writesmatch n <= 0 { true -> base; false -> recur(n - 1) }(or the equivalentmatch n < 1 { ... }) are now treated as self-guarded byinfer_decreases, so the lowerer emitsdecreases if n >= 0 then n else 0without arequires n >= 0precondition the user never wrote.examples/data/rle.av'srepeat(char_, n)shape closes (theexpandRun(run)caller no longer has to proverun.count ≥ 0).
Tooling
tests/proof_specgatesdafny verifyon the IR-clean examples and tracks per-examplesorryand Dafny-error budgets across both backends. Lean: three examples carry honestsorrybudgets (json.av13 sampled-domain laws,rle.av2,quicksort.av2). Dafny: the flagship examples whose proofs Dafny still can't auto-discharge —fibonacci(1),rle(4),quicksort(5),date(2),json(113) — are now gated by an error-count budget instead of being silently unverified. Drift either way fails the test, so a new shape regressing or an old gap closing both surface in CI.aver compile --emit-ir-after={refinement_lower,contract_lower,law_lower}exposes the three new proof-lower stages — when a law falls through tosorry/empty-body,law_lowershows whether the lowerer pinned a strategy or fell back toBackendDispatch.
Backend foundation
- Every backend (Rust, Lean, Dafny, wasm-gc) now consumes one typed view of the program. Pre-Lift each backend carried its own string-keyed fn-signature side-channel (
ctx.fn_sigs) and re-derived types by parsing source-annotation strings on the fly during emit; identity decisions (whichShapedoes this constructor refer to? which dep module'sBoxis at this slot? is this callee pure?) lived in fragile bare-name lookups that could silently drift between backends. Lift consolidates the codegen substrate around one resolver-produced view of the post-name-resolution program — typed(name, Type)parameter lists, typed return types, opaqueFnId/TypeId/CtorIdidentity, and a.ty()slot on every reachable body expression — and the bare-string fn-signature cache is gone. A guardrail test (tests/identity_guardrails.rs) blocks any new backend code from regressing to the old patterns. The most visible payoff: two dep modules can each declarerecord Box { value: Int }and compile cleanly onaver compile --target wasm-gc(pre-Lift the post-flatten type registry collided them under one slot andLeft.Box(value = 5).value + Right.Box(value = 10).valuefailed wasm validation), and==/!=on those records dispatches to the right per-type equality helper rather than silently picking the last writer. Single-declarer dep types stay on the legacy bare-key path with no behavior change; the next major IR step (MIR / Core IR for per-expression effects + ownership + cross-scope optimisation) lowers from this substrate, separate epic. String.fromFloatonaver compile --target wasm-gcnow matches VM and wasip2 to the last shortest-roundtrip digit. The wasm-gc WAT helper capped the fractional-digit loop at 15 to avoid ani64.trunc_f64_strap on large-magnitude inputs, but the cap also chopped one digit off values in the[0.1, 10)range where the multiplication doesn't overflow —goldenApprox(n) = Float.fromInt(fib(n + 1)) / Float.fromInt(fib(n))fromexamples/data/fibonacci.avprinted1.618181818181818on wasm-gc vs1.6181818181818182on VM. The cap is now 17 (the IEEE 754 f64 maximum); the overflow guard above it still bails before the trap on large magnitudes, so behaviour for values outside[0.1, 10)is unchanged.Console.print/Console.error/Console.warnonaver compile --target wasip2now append the trailing newline that VM and--target wasm-gcalready shipped. Pre-Lift wasip2's lowering wrote only the string bytes to the wasi output stream, so a sequence ofConsole.print("a"); Console.print("b")came out asabonaver run --wasip2anda\nb\neverywhere else — multi-line programs on wasip2 produced one jammed line. Theprintln!semantic now lives in a dedicated__rt_println_to_lmbridge helper called by all three Console.* methods; other consumers of the bridge (Disk.writeText,Http.*marshalling) stay on the no-newline__rt_string_to_lmand are unaffected.
Examples
- New
examples/refinement/collects the canonical refinement-via-opaque demos:Natural,Positive,IntRange,NonNegFloat,Email,BigInt. Each exercises a different point in the design space.
Hardening
- Functions with wildcard
_parameters (fn f(_: Int)) compile and run cleanly on every backend. Pre-Lift the resolver short-circuited_and never claimed a slot for it, solocal_countstayed at zero while callsites still pushed one value per source-level param —aver verifyon a program likefn ignore(_: Int) -> Int = 42thenignore(7) => 42deterministically panicked inside the VM dispatch loop. The resolver now allocates a slot for every param regardless of name; wildcard params still skip the scope map so the body cannot read them, but the frame layout matches what callsites push. Found byfuzz_verify_runnerAFL nightly.
Aver 0.21.1
Verify
aver verify --hostilenow exercises a third axis: execution order. Everyverify <fn> lawcase whose fn contains an(a, b)!independent-product gets a twin run in which the branches execute right-to-left, with each result placed back into its source position. A pure law claims its independent products commute, so the twin's tuple must match the forward run; a mismatch surfaces asverify-hostile-mismatchwith origin+reverse-eval. Catches the class of bug where the runtime, the stub map, or a compiler optimisation has snuck a hidden ordering dependency into code Aver was treating as order-invariant. The most common shape it catches: a law that pins a trace event by flattrace.event(k)(which indexes the global emission sequence, so reverse-eval moves it) instead of structuraltrace.group(g).branch(b).event(k)(which addresses by source position and stays order-invariant). Same--hostileflag — no new CLI surface, no source-language change. New worked example atexamples/formal/hostile_order_axis.av; the diagnostic's repair message names the right rewrite when it fires.
Aver 0.21.0 "Iron"
Iron in the frame — the type checker stops lying to itself about negation, recursion, and identity. A new fuzz harness shakes the rest of the toolchain until things fall out.
Type checker
- Duplicate
fnnames in one module are a type error. Pre-Iron the second definition silently replaced the first — a typo could swap a function's body with no signal. - Polymorphic recursion that would need
T := F<...T...>is rejected. A shape likefn nest(v: A) -> Unit; nest([v])now surfaces as a normal type-incompatibility error instead of silently typechecking with a circular binding that later confused backends. - Two same-named types from different modules don't conflate. A project importing
A.Shape(Circle | Square) andB.Shape(Triangle | Hexagon) used to silently accept aB.Shapevalue whereA.Shapewas expected. Now rejected withexpected A.Shape, got B.Shape; the legitimate same-name-same-type case still type-checks. - One source error stops at one diagnostic.
let z = add(unknownFn(1), unknownFn(2))reported the two real errors plus two follow-onexpected Int, got Invalidcascades; the recovery sentinel is now treated as a wildcard so callers see only the originating diagnostic. - Unreachable
matcharms are rejected. A second_ -> ...(or a repeated0 -> ...) used to compile silently — the second arm could never fire because Aver match is first-arm-wins, but nothing flagged it. The type checker now reportsUnreachable match arm: pattern X is already covered by an earlier arm at line N, naming the covering arm so you can pick which one to delete. Catches duplicate wildcards, identical literal patterns, identical constructor patterns, and structurally-equivalent tuples.
Parser
- Deeply-nested expressions return a parse error instead of crashing
aver. Sources with 2500+ nested(...),Option.Some(...),{...}, chained-, chained?, or deeply-nested match patterns used to abort the process withfatal runtime error: stack overflow. The parser now caps recursion at 64 levels and surfacesExpression too deeply nestedas an ordinaryparse-error.
Runtime
-0.0keeps its sign bit on every backend. Pre-Iron-xdesugared to0 - x, and0.0 - 0.0collapses to+0.0under IEEE 754. Unary minus is now a first-class AST node and every backend negates at the float bit level, so-0.0round-trips through compile + eval + replay.-xon tight numeric loops is faster. Typed unary-minus dispatch on the VM joins the typed-arith pipeline (so-xruns at the same shape as+/*//for known-Int/ known-Floatoperands).- Hand-edited compiler inputs surface as compile errors, not panics. Sources that registered two meanings under one symbol (duplicate variant constructor with conflicting payload, constant rebound under a function name, empty namespace path) used to panic the VM compiler; they now surface as
Compile error: VM symbol 'X' already exists as ...with a source span.
Replay
aver replayaccepts every recording shapeaver run --recordwrites. Three places where replay refused or panicked on legitimate input got fixed: recordings touchingVectorvalues, single-string-keyMaprecordings (collided with the marker shape), and any JSON containing multi-byte UTF-8 in an unexpected position (the JSON keyword parser sliced&strand panicked onbyte index N is not a char boundary).
wasm-gc backend
String.fromFloat(x)doesn't trap at1e4–1e18magnitudes. The shortest-roundtrip loop overflowedi64.trunc_f64_sand the module crashed withwasm trap: integer overflow. The loop now bails one iteration before overflow, accepting fewer fractional digits at very large magnitudes instead of a crash.Result<Unit, X>andTuple<Unit, X>compile. The carrier-equality codegen path had noUnitarm and rejected typecheck-clean programs that used these shapes (e.g.fn animate() -> Result<Unit, String>).Console.printfrom in-process embedders is captured correctly. When the host called wasm-gc-compiled code inside a thread-local stdout capture,Console.printwrote directly to fd 1 and bypassed the buffer — programs looked silent from the host's view even though they did print. The wasm-gc Console import now routes through the same capture path the VM uses.
Verify
aver verifywon't hang on a non-terminating case. Averifyblock whose function had no terminating recursive base case (an easy shape to write by accident, and the one the fuzz harness reproduces every nightly) used to spin in the VM forever. The runtime now caps per-case work at 10M VM opcodes (mirrored as a wasmtime fuel budget onaver verify --wasm-gc); over-budget cases surface asRuntimeError: VM step limit exceeded, not a hang.
Tooling
- Iron ships a multi-target fuzz harness. Eight AFL++ targets run nightly against
main: frontend (lex + parse + typecheck), codegen on three backends (wasm-gc / wasip2 / Rust), VM-vs-wasm-gc parity (in-process, ~300 execs/s), verify runner, replay record→replay roundtrip. Plus a custom AST-aware mutator that produces typecheck-clean inputs reaching the codegen + verify layers byte-havoc rarely touches. Every "the parser used to crash" / "the backend rejected a typecheck-clean program" bullet above was found by this harness during Iron development. PR-side cost is zero — fuzz only runs nightly + on manualworkflow_dispatch. aver verifyruns on--wasm-gc. Cross-target check — catches divergence between VM and wasm-gc on equality. Pure value-givens and value-hostile cases supported; trace projections, classified-effect Oracle stubs, andBranchPathcases reject upfront with an actionable pointer back to the VM verify path.- Snapshot regression suites per backend.
examples/corpus walks under wasm-gc + wasip2 codegen on every PR (≈0.1s each), Rust codegen + Lean + Dafny build under nightly. A compiler refactor that breaks codegen on a vetted example fails a named test instead of an obscure end-to-end break.
Aver 0.20.0 "Pulse"
The same Aver source that opened HTTP both ways in 0.19 now opens raw TCP — connect, send, receive, ping. One pool, one handle shape, every backend the same.
Added
- TCP client on
--target wasip2. All six methods —Tcp.connect,Tcp.writeLine,Tcp.readLine,Tcp.send,Tcp.close,Tcp.ping— compile and run as components againstwasi:sockets/*. Long-livedconnect/writeLine/readLine/closeshare a 256-slot pool keyed by"tcp-N"(same id shape every other backend uses, so cross-backend code stays portable);sendandpingare ephemeral (no pool slot), so a program holding 256 live connections can still issue either. Run withwasmtime run -W gc=y -W tail-call=y -S inherit-network=y -S allow-ip-name-lookup=y -S tcp=y, or viaaver run --wasip2. Seedocs/wasip2.mdfor the per-method status table.
Aver 0.19.0 "Echo"
Aver speaks HTTP both ways now — same source can call out as a client and answer back as a server, the same
.component.wasmruns on Cranelift and V8.
Added
- HTTP client on
--target wasip2. All six methods —Http.get,Http.head,Http.delete,Http.post,Http.put,Http.patch— now compile and run as components. Response headers surface asMap<String, List<String>>; multi-value headers (e.g.Set-Cookie) keep server emit order. Failure messages name the wasi:http error variant (http: connection-refused,http: DNS-timeout, …) instead of a generic string. HttpServer.listenon--target wasip2 --world wasi:http/proxy. Write a handlerfn(HttpRequest) -> HttpResponse, name it via--handler <fn>at compile time (same flag the wasm-gc + Cloudflare path uses), compile to a.component.wasm, and serve it with any wasi-http host —wasmtime serve --addr=:N, Spin, NGINX Unit, wasmCloud. Request method / path / query / body / headers surface inside the handler as ordinary Aver values; the response's status code, body bytes, andMap<String, List<String>>headers round-trip to the client. The same source keeps working underaver runbecauseHttpServer.listen(port, handler)inmainis still a real call under VM — it just lowers to a no-op when the wasip2 proxy codegen takes over (which reads the handler identity from the flag, not frommain).HttpServer.listenWith(per-instance context handler) stays deferred for one more iteration.
Aver 0.18.0 "Span"
Cross the Component Model boundary the same way Aver crosses the source/wasm one — typed effects in, canonical-ABI imports out.
Added
--target wasip2. WASI 0.2 / Component Model output. Wraps a wasm-gc core module viawit-component, lowers Aver effects directly to canonical-ABI WASI imports (no preview-1 adapter, no--bridgeshim). Emits.component.wasm+ sibling.wit. Effect surface:Console.{print,error,warn,readLine},Args.get,Env.get,Time.{unixMs,now,sleep},Random.{int,float}, all 7Disk.*methods (exists/readText/writeText/appendText/delete/deleteDir/makeDir/listDir).Env.setandTerminal.*reject at compile time as structurally absent from WASI 0.2;Http.*/Tcp.*/HttpServer.*deferred to 0.19+. Seedocs/wasip2.md.aver run --wasip2— embedded wasmtime +wasmtime-wasirunner. CWD preopened as.for filesystem effects (matches VM target's path resolution semantics).tests/wasip2_stress.rs— six regression tests covering 100× write+read+delete (resource leak), 50KB write/read roundtrip (chunked-write boundary), 5KB Console.print (chunked-write on stdout side), 200-entry listDir, Random distribution sanity, Time.sleep precision.
Removed (breaking)
--target wasmdeleted. The pre-2024 NaN-boxed wasm32 backend (src/codegen/wasm/, ~9.5 kLoC) is gone, plus thewasm-legacyCargo feature, the--bridge {wasip1,fetch,none}flag, theaver wasm-runtimesubcommand, and the legacy bundling code insrc/main/commands.rs. Modern hosts run--target wasm-gc; standalone runtimes use--target wasip2.--target edge-wasmwent too — it depended on the deletedcodegen::wasm::emit_wasm_with_adapter.BenchTarget::WasmLocalremoved — bench targets are nowvm/wasm-gc/wasm-gc-v8/rust.
Internal
module.rs/builtins.rs/types.rssplit.wasm_gc/module.rs5984 → 4197 (extractedwasip2_helpers.rs);body/builtins.rs2351 → 1740 (extractedbody/builtins_wasip2.rs);wasm_gc/types.rs2778 → 1934 (extractedtypes_discovery.rsforcollect_*AST walkers). Pure code movement, no behaviour change.