Skip to content

vilan 0.10.0

Choose a tag to compare

@github-actions github-actions released this 20 Jul 04:15
47ffd38

Resources: values that clean up after themselves. A resource struct (or resource external struct) is the new owned-resource class — a value with exactly one owner that moves on binding and own-passing instead of copying, is loaned through the ordinary view conventions, and runs its Drop at its owner's scope end, every exit included (ret, jump, panic unwinding — and a value-returning main now runs its drops before the process exits). Containment infers: a struct, enum, tuple, or fixed array holding a resource is one. Option.take/replace are the sanctioned partial move, std's drop(value) destroys early with no public close() anywhere, and the affine checker rejects the whole double-close family at compile time — use-after-move (with a note at the move), conditional moves, moves in loops, resource captures in closures and spawns, resources in native containers, coercions to any, and derives (Wire/Hashable/PartialEq) on resource-holding types. Database is the first real resource: it closes its node:sqlite handle deterministically, module-level handles keep process lifetime (the serve-forever idiom — now loan-only, and reachable from closures, which the checker previously miscounted as captures), and OwnedNursery owns background tasks whose real failures still reach the console with their spawn origin while cancellation echoes stay silent. The resources tour walks it; spec §6.8 is the contract.

One law now opens the memory model. Spec §6.0: every alias is a claim on an owner whose epoch advances on a fixed set of events — and a claim is valid while its owner's epoch is unchanged. Views are the statically-proven claims, handles the dynamically-checked ones, and every mechanism in the chapter (views, projections, Arena/Handle, Shared, resources) is presented as a cell in that one table.

Rule 4 is now enforced everywhere views actually come from — and it's smarter about what invalidates. Previously only a direct &place view was policed; a view returned through a call (list.at(0), arena.get(h)) or bound by a Some(let v) match capture was invisible to the invalidation checks (and a chained projection didn't even lower as a view — a real miscompile, fixed). Now every view anchors at what it projects, multi-parameter projections anchor at all of them, and mutating a viewed container, reassigning its root, or holding any of these across await is the same compile error the direct form always raised. This can reject code that previously compiled — re-derive the view after the mutation or suspension, as ever. In exchange, the checker stopped over-rejecting: only calls that may change a container's geometry (grow, shrink, reallocate, swap an aggregate field — inferred per method as the new bumps effect, hover-visible beside borrows) conflict with a live view; a method that merely writes fields or elements through &mut self now passes freely.

Arena.get hands back a live viewOption<&T> borrows self, the shape the spec always described, instead of a copy; set remains the write path, and stale handles still answer None.