Repository navigation
Hew v0.6.1
Hew 0.6.1 adds reusable generic closures, typed configuration embedded at compile
time, deeper machine hierarchies and confinement around supplied services. It
also improves actor deadlines and native execution, and updates the TLS library
to address upstream security advisories.
Upgrading from 0.6.0
- Upgrade communicating peers together. The wire protocol changes from v2 to v4;
earlier versions are rejected explicitly. Put shared protocol declarations in
imported modules with portable dotted owner paths, rather than separate
executable roots. Calls now carry canonical declaration identities and
inherited request budgets, with no numeric handler-hash fallback. - Keep each node's identity file when upgrading. Set
NodeConfig.keyto a
non-empty path before callingNode.start(config);NodeConfig.at(address)
leaves that field empty. Startup reads an existing key or creates one when
absent. Keep the file private and back it up: replacing it changes the
node's identity and the credentials its peers must pin. A wrong-size TCP
key file is refused rather than regenerated. - Use
NodeTransport.TcporNodeTransport.QuicMeshfor distributed nodes,
with configured peer credentials. The legacyHEW_TRANSPORT=quicselector
is still recognized in 0.6.1, but cannot supply the credential binding that
authenticated node startup requires. It is not an unauthenticated mesh
option.std.net.quicremains the separate QUIC socket API. - Review computed machine transitions. A computed
_target exits the full
active branch, evaluates the body once, then enters the returned branch,
including same-leaf and sibling returns. Use named targets when a transition
should retain shared ancestors and run hooks only along the changed branch. - Update TLS-dependent applications. Hew 0.6.0 bundles rustls 0.23.45; this release
updates it to 0.23.46, addressing
RUSTSEC-2026-0346,
0347,
0348 and
0349. - Packages using the new language features can declare
hew = ">=0.6.1"in
hew.toml.
Generic helpers
Generic closures declare type parameters after the opening pipe, as in
|<T: Eq> left: T, right: T| -> bool { left == right }. Store or return them with
a type such as fn<T: Eq>(T, T) -> bool. Callable qualifiers use the usual
fn[qualifiers]<T: Bound>(T) -> R spelling. Calls infer concrete types or accept
an explicit type list. All instantiations share the same captured state; mutable
and once-only invocation rules apply across the whole closure value.
Generic functions can constrain associated-type projections with
where I.Item: Display or where <I as Iterator>.Item: Display. These bounds
carry through imported helpers and generic closures on native and sandbox
execution, including equalities such as Iterator<Item = T>.
Trait implementations obey shared package ownership and overlap rules across
native compilation, virtual package inputs and editor analysis. Generic and
blanket implementations use the same checked declaration identities.
Compile-time data and generation
embed!(path) reads JSON, YAML or TOML at compile time and checks it against the
expected concrete type and its ordinary serialization schema. Generated programs
construct ordinary values without decoding the file at runtime. Repeated uses
retain independent value semantics. Invalid data names its input file and field
path; embedded collection keys with custom equality are rejected. Native and
sandbox execution share these semantics, including target-specific integer
range checks.
location!() produces an ordinary SourceLocation constant. Ordinary constants
also support records, enums, tuples and collections, including record updates
and vector spreads, through the same checked value representation.
Declarative macros preserve definition and caller binding contexts across native
and sandbox compilation. Function and method attribute macros compose in stacks;
the CLI, editor and browser analyzer use the same expansion pipeline. Declared
generators run through hew generate, with tracked inputs and check mode.
Machines and actor calls
Composite machines support deeper nesting and recursive initial-child descent.
Child rules precede the nearest ancestor's rules, with guarded fallback. Parallel
regions and history states remain unavailable.
Actor interceptor chains preserve caller identity, refusal and cleanup
behaviour. A refused call has no response value.
Actor calls that wait for a reply inherit the earliest scope and incoming
request expiry.
Expired queued calls never start. A claimed handler remains owned by its actor,
while its nested calls return TimedOut once the inherited budget is exhausted.
Caller expiry abandons the reply and cannot undo a remote mutation. Local native
and sandbox execution share that boundary; distributed asks carry relative
budgets and authenticated best-effort withdrawal of queued requests. Caller
expiry and cancellation remain responsive when another sender or a peer stalls
transport progress. Required ownership cleanup remains shielded from the
abandoned request deadline.
Confinement with supplied services
Actors and ordinary functions can use #[confined] to reject transitive ambient
authority acquisition and opaque native escapes. Opened std.fs.ReadFile and
WriteFile resources provide directional access to one file, supplied once at
construction. Ordinary helpers, captured callables, trait implementations and
required cleanup preserve that boundary. Generic libraries can be checked in
isolation; concrete calls and constructions discharge their supplied-service
authority obligations. Incomplete authority summaries, including erased
generator execution or cleanup, are refused conservatively.
std.fs.ReadDir and WriteDir extend this wiring to a directory tree. Their
operations accept relative child paths, subdir narrows the root, and
open_read or open_write opens an independently owned directional file.
Contained relative symlinks work; absolute paths, parent escapes and escaping
symlinks are refused. Opened files and narrowed roots remain usable after the
parent resource closes. An opened root follows its directory if renamed; some
hosts refuse renaming an open directory. Acquiring a directory is ambient
authority and remains unavailable inside a confined component.
The same domain interfaces support in-memory services on the browser VM. File
and directory resources run natively. Cross-node capability delegation remains
separate; confined code continues to refuse remote acquisition.
Runtime and native execution
Inbound distributed actor asks wait through scheduler readiness instead of one
blocked OS thread per request. Pending replies are bounded per destination actor
incarnation, so a slow service does not occupy unrelated services' ask capacity.
Native coroutine lowering uses LLVM's switched-resume machinery for frame
splitting and optimization. Proven synchronous callables avoid child coroutine
states; implicit resource cleanup participates in source suspension effects.
Scalar vector replacement and last-use actor payload transfers avoid redundant
allocation and reference-count work.
Function values avoid redundant allocations during construction and release.
String comparisons in the browser VM use the same UTF-8 ordering as native
programs, including characters outside the Basic Multilingual Plane.
Compiler fixes
Large applications containing ordinary records and enums no longer repeatedly
trace those values for scoped tasks when their types cannot hold tasks or
captured callbacks. Types that can carry either still receive the lifetime
checks, including positional records that wrap a callback.
Parent-relative imports such as import "../worker.hew" now compile when the
imported module defines a generic actor; these imports previously triggered a
compiler panic.
Known publishing limitation
hew publish can fail with E_PUBLISH_MISSING_INPUT when a package uses
installed package dependencies. It incorrectly requires those dependency files
inside the package's own archive. Installing and running already-published
packages remains supported.
Platforms and next steps
Native SDKs target Linux, macOS, Windows and FreeBSD. Install the SDK for your
platform, or use the browser playground for sandbox execution. The
language specification
provides the syntax and behavioural contracts; the
full changelog
covers the changes since 0.6.0.