std::builtinsBuilt-in functions available in every Hew program.
These functions are always in scope — no import is needed.
They cover I/O, assertions, math, string operations, and
program control flow.
printlnPrint a value followed by a newline.
Accepts any type that implements Display.
fn main() {
println(42);
println("hello");
println(true);
}
printPrint a value without a trailing newline.
fn main() {
print("Enter name: ");
}
assertAssert that a condition is true, raising a recoverable logical fault when it is false.
A failure reports the condition's source text. When the condition is a
comparison (==, !=, <, <=, >, >=), both operands are evaluated
once and shown, with a line diff when either value spans lines. The
optional second argument, assert(condition, message), is a string
evaluated only when the assertion fails.
fn add(a: i64, b: i64) -> i64 {
a + b
}
fn main() {
assert(add(1, 2) == 3);
assert(add(2, 2) > 3, "sums grow");
}
to_stringConvert any value to its string representation.
Accepts any type that implements Display — this includes all numeric
primitives, bool, char, string, and user types with a Display impl.
fn main() {
let s = to_string(42); // "42"
let t = to_string(true); // "true"
let u = to_string('x'); // "x"
}
sleepPause execution for the given duration.
The caller suspends cooperatively (inside an actor handler) or blocks the
thread (in fn main / free functions).
Sub-millisecond values behave differently depending on the execution context:
500ns) becomes 0ms, which
arms a zero-deadline timer wheel entry and still suspends and resumes the
actor at the next scheduler tick. The actor is never truly sleeping for
the nanosecond count.fn main / free functions (blocking): the OS sleep is requested at
full nanosecond precision. sleep(500ns) sleeps for approximately 500 ns
(subject to OS timer granularity, typically ≥1 µs on Linux/macOS).sleep(500ns) becomes sleep(1ms) on WASM.fn main() {
sleep(10ms); // sleep for 10 milliseconds
sleep(2s); // sleep for 2 seconds
sleep(500ms); // sleep for 500 milliseconds
}
sleep_untilPause execution until the given monotonic instant.
If target is already in the past, returns immediately. Use
instant + duration to construct a future instant:
fn main() {
let deadline = instant.now() + 10ms;
sleep_until(deadline); // wait until 10 ms from now
}
The instant + duration operation adds a duration offset to a monotonic
timestamp, returning a new instant. The commutative form
(duration + instant) also works.
fn main() {
let deadline = instant.now();
// ... do work ...
sleep_until(deadline); // wait until the deadline if not yet reached
// Sleep for exactly 50 ms from a fixed reference point:
let t0 = instant.now();
// ... do work ...
sleep_until(t0 + 50ms); // accounts for time already spent
}
exitTerminate the program immediately with the given exit code.
This function never returns and does not run scope cleanup. Return from
main for orderly cleanup. An unrecovered fault instead reports its
diagnostic and exits with status 1 on the native path.
panicTerminate the program with an error message.
This function never returns.
fn main() {
panic("something went wrong");
}
ChildRefA stable reference to a supervised actor role.
Unlike an actor handle, a ChildRef<T> never snapshots an actor
allocation. Each operation resolves the role's current incarnation through
its owning supervisor and returns an error while the child is unavailable
or stopped.
NodeIdStable key-derived node identity.
LocationComplete remote actor location.
NodeConfigNodeErrorA node lifecycle operation could not apply the supplied configuration.
ConfigRemotePidAn actor pid on a remote node carrying its complete actor location.
Produced by authenticated peer discovery. Does NOT coerce implicitly to a local actor handle — a remote actor is a distinct class with its own physical representation.
The intended remote call contract uses the same completion calls and mailbox submission views as local actors, with typed transport failures. Native transport lowering exists, but final-compiler distributed lifecycle acceptance remains incomplete. These declarations alone do not establish end-to-end native or sandbox support.
ActorMailboxAn immutable one-way view for void receive handlers. Construct one with mailbox(target, on_full: ...).
A receive call through the view submits under that policy and returns as
soon as admission or a policy-selected discard is resolved. The policy
type records whether submission can suspend. A call on the actor handle itself waits for the
handler to finish instead.
ActorPolicyAn immutable completion view choosing how its own calls are admitted.
Construct one with policy(target, on_full: ...). A call through the view
waits for the handler exactly as a call on the actor handle does; the
policy decides only what happens when the destination mailbox is full.
.Wait is the bare-handle behaviour; .Reject yields
ActorError.Rejected(failure) instead of parking the caller.
MessageOwned request description for one-way submission recovery.
Consuming retry() and to(target) retain the request's typing.
ActorRequestOwnerInternal owner of an unaccepted completion request.
ActorRequestAdmissionActorRequestThe request protocol is a sealed, inferred type parameter. The original payload stays inside its runtime owner until admission or cleanup.
SendFailureA rejected submission retains its complete unaccepted message.
DeliverySuccessful submission describes acceptance or a discard. A discard is a
loss either the destination's declared mailbox policy or the sender's own
on_full chose; the message is gone either way and nothing is retryable.
AcceptedDiscardedOnFullA sender chooses how its own submission responds to a full mailbox.
RejectWaitDropNewestReplaceLatestRejectSendWaitSendDropNewestSendReplaceLatestSendSendErrorError returned when a send cannot be completed.
FullThe destination mailbox is full.
ClosedA sink or connection has closed.
PartitionThe route to the peer is unavailable or the peer is suspected dead.
StaleRefThe pid refers to an old session or actor incarnation.
LocalShutdownThe local node is shutting down before the send can complete.
CancelledThe caller cancelled the send before it completed.
VersionMismatchThe peer rejected the send because protocol or schema versions differ.
UnauthorizedThe peer rejected the send because the caller lacks authority.
BackpressureThe destination or route is applying flow control.
DeadThe destination actor accepts no more messages.
LookupErrorError returned when Node.lookup<T>(name) cannot resolve name.
Returned as Err(LookupError.NotFound) when no actor is registered
under name on the current node (or any peer with a gossiped name).
Future variants (e.g. transport-level failures, schema mismatches) are
deferred to follow-on polish; today the runtime collapses every failure
into NotFound since the underlying registry surface is fail-closed
per set_last_error for the diagnostic detail.
NotFoundNo actor is registered under the requested name.
PartitionThe lookup route is unavailable or the peer is suspected dead.
StaleRefThe name resolved to an old session or actor incarnation.
CancelledThe caller cancelled the lookup before it completed.
LocalShutdownThe local node is shutting down before the lookup can complete.
VersionMismatchThe peer rejected the lookup because protocol or schema versions differ.
UnauthorizedThe peer rejected the lookup because the caller lacks authority.
NeverThe error of a handler that cannot fail.
Never has no values, so ActorError<Never>.Failed can never be
constructed: a call on an infallible handler reports transport and
lifecycle outcomes only.
ActorErrorError of a completion call on an actor handle.
E is the handler's declared fails type — Never when the handler
cannot fail. Req carries an unaccepted request when admission may reject it.
Omitted parameters default to Never.
Only Rejected is safely retryable: nothing was accepted, so the caller
may make the same call again. Every other variant means the request was
accepted or its fate is unknown, so repeating it would duplicate work.
Rejected(SendFailure<Req>)Nothing was accepted. failure.reason explains why;
failure.message.retry() or .to(target) consumes the sealed request.
Failed(E)The handler ran and returned its declared error.
TrappedThe handler faulted; its actor retains ownership of the fault.
DeadThe destination actor is gone and will not come back.
TimedOutThe caller's deadline elapsed before a reply arrived.
NodeNotRunningThe local node is not running.
RoutingFailedThe destination node or actor could not be routed.
EncodeFailedThe request payload could not be encoded.
ConnectionDroppedThe remote connection closed before the reply arrived.
PartitionThe route to the peer is unavailable or the peer is suspected dead.
LinkErrorFailure to subscribe to an actor's exit through link or monitor.
Both operations require a current actor to receive the notification; a
target that is already dead or unreachable is not an error, it answers
with an immediate exit or DOWN.
NoContextVecIterCursor iterator over a Vec<T> produced by vec.into_iter().
VecIter<T> is the concrete IntoIterator.IntoIter for Vec<T> — it
pairs the owned vector with the current idx cursor so that
for x in v { ... } (for-loop desugar) and the lazy combinators in
std/iter can drive iteration through the trait surface rather than the
per-type *_int / *_str / *_f64 table.
next takes a mutable receiver: each call reads the current element and
then bumps self.idx in place via a field-store. idx advances once per
call until it reaches the vector's length, after which every subsequent
next returns None. The receiver remains Live after exhaustion and
drops at scope exit — see the Iterator trait doc-comment.
Vec is a refcounted heap handle, so the cursor carries the underlying
vector storage by handle (no per-step copy).
In a generic body with unbounded T, indexing and ordinary for loops
borrow elements consistently across instantiations. Use into_iter() to
consume the vector and obtain owned items, or explicitly clone an item
under a T: Clone bound. The current owned cursor may still clone elements
when their type supports cloning; consuming the vector does not promise
clone-free iteration.
Lives in std/builtins.hew rather than std/vec.hew so it registers
alongside the Vec Index impl through register_builtins_hew_impls (the
per-stdlib-module receiver-impl harness only handles a fixed set of
receivers; auto-registration on builtin nominals belongs in builtins).
HashMapIterCursor iterator over a HashMap<K, V> produced by map.into_iter().
HashMapIter<K, V> snapshots the map's keys and values into two parallel
Vecs at construction (HashMap.into_iter) and walks them by a shared
idx. The keys and values are taken from the SAME map state in the same
projection order, so ks[i] and vs[i] are the matching key/value of one
entry. Each yielded (K, V) is a FRESH, independently-droppable owner: the
keys() / values() projections clone every element into the owned Vec
(the same clone-on-read discipline as the Index<K> accessor), and the
cursor only borrows those snapshot Vecs — it never co-owns a yielded pair
with the source map (drop-allowset-from-value-flow,
by-value-heap-params-are-borrows).
next mirrors VecIter.next: read (ks[idx], vs[idx]), bump idx in
place, and return None once the cursor passes the snapshot length. The
receiver stays Live after exhaustion and drops at scope exit — the
Iterator "exhaustion ≠ drop" invariant.
ScopeFailureA structured scope failure, available only after child and deferred cleanup. Parent cancellation propagates to the enclosing scope and is not recoverable here.
Deadline { message: string }Fault { message: string }ActorMsgMessage contract for actor types addressed through RemotePid<A>.
An actor binds Msg to the envelope type accepted by .send / .ask and
Reply to the response type returned by .ask.
IteratorProduce a sequence of values one item at a time.
User-defined iterators implement this trait directly; for loops accept
values whose type implements IntoIterator and walk the resulting
Iterator to bind each yielded Item.
next takes its receiver mutably (var self): iterator implementations
step their internal state in place (cursor advance, decrement remaining,
flush a buffer) and surface successive items through the
Option<Self.Item> return. Callers must hold the iterator in a var
binding so that the mutated receiver remains observable between calls;
binding the iterator with let is rejected by the checker with a
"receiver requires mutable binding" diagnostic.
Iterator methods with mutable receivers keep the iterator Live past
exhaustion; drop fires at scope exit, not at the None return. This is
a deliberate shift from a hypothetical by-move shape: exhaustion is a
Some → None boundary, not a lifetime boundary. Iterator implementations
that own non-shared resources (heap-owning buffers, channel readers)
inherit the "exhaustion ≠ drop" invariant — see the lifecycle-symmetry
invariant in docs/internal/engineering-invariants.md.
IntoIteratorConvert a value into an Iterator.
For trait-based iteration, a for loop creates a mutable iterator and
calls next() until it returns None. The item type is
<Self.IntoIter as Iterator>.Item. Built-in collections also support
borrowed iteration; a loop over an unbounded generic Vec<T> borrows its
elements rather than taking ownership of them.
IntoIter carries the Iterator<Item = Self.Item> bound so that callers
projecting <T as IntoIterator>.IntoIter.Item always agree with
<T as IntoIterator>.Item. Concrete IntoIterator impls live next to
each collection (Vec, HashSet, HashMap); this trait declaration
reserves the surface only.
Indexc[i] and c.get(i) for EVERY indexable collection resolve through this
trait. A new collection type gets both accessors by writing one impl —
no compiler change (the A195 mandate).
get(self, i) -> Option<Self.Output> is the FUNDAMENTAL safe accessor:
None on out-of-bounds/absent, else Some(elem) where the payload is a
FRESH, independently-droppable owner (retain-share for strings, deep
clone for owned records/enums, by-value for scalars). The container is
borrowed, not consumed.at(self, i) -> Self.Output is the TRAPPING accessor: c[i]. It asserts
presence and traps (TrapKind.IndexOutOfBounds) on absence.Idx is a trait TYPE PARAMETER (not an associated type) so a collection may
index by more than one key type (Vec/bytes/string by i64; HashMap
by K), and a future Index<Range> slicing convergence is accommodated.
Leaf containers (Vec/HashMap/bytes/string) carry intrinsic bodies the
compiler lowers directly (the index_get/index_at lang-items); user
composites write ordinary Hew bodies that delegate to a leaf's get.
DisplayConvert a value of type Self into a human-readable string.
Implementing Display for a type lets it flow through print,
println, to_string, len, and stop.
The trait method must return a string derived from the receiver
without invoking print itself (otherwise the output path becomes
recursive).
Blanket impls below cover the primitive numeric kinds, bool,
char, and string; user types add their own impls per receiver.
ErrorThe marker an error type carries so it can be erased to dyn Error.
Error adds no methods of its own: an error is a value that can say what
went wrong, so Display is the whole obligation. Declaring
impl Error for MyError {} therefore requires impl Display for MyError.
FromDeclares that a Source error converts into Self where a failure
leaves a function. ? and return error apply it; everywhere else the
conversion is the explicit call Target.from(value).
A conversion never chains, and erasure into dyn Error needs no impl.