Date: 2026-07-06
Two independent deep-research passes on the compiler-ready standard library converged on refinements to the layer plan below. They are research input, not accepted design; apply them through the stdlib work order (after the callable-spine work order), not by rewriting this doc now. See research/2026-07-12-minimum-compiler-ready-stdlib-triage.md for the full triage and sources. Summary of the refinements to weigh:
- The compiler-ready dependency closure is deliberately larger than the
permanently stable stdlib: do not freeze interning, typed compiler IDs,
arenas, SCC/graph utilities, or backend helpers as stable
stdjust because the first compiler needs them. Use maturity states bootstrap-private / foundation-experimental / stable. - Move
std.text(and no-alloc UTF-8) earlier: a self-hosting compiler is a text processor first. - Add
std.osas its own layer (opaque path/name + target facts), mapping onto the shipped native Path boundary; never treat a path asText. - Split compiler-essential literal decoding from any generic
parseframework (generic parsing is post-self-host). - Add a minimal
compiler.backendemission path (bytecode / emit-C / object) to the pre-self-host line; it seeds a future backend-selection decision tied to the.exe/.dllstory. - Model three distinct error channels (operational failure, source diagnostics, compiler-invariant failure) rather than one; this aligns with decision 0016.
- Prefer compact typed IDs over
Rc/Arcfor compiler graphs; reference counting is not part of the minimum library (aligns with decision 0014). - Prove self-hosting as a stage-2 fixed point: semantic equivalence first, byte-identical reproducibility later under a declared profile.
Hum should not start by writing a giant standard library in Hum.
That would feel productive and probably be wrong. A language without a stable parser, type checker, ownership model, effect checker, and benchmark harness cannot honestly decide what its standard library guarantees. It can sketch APIs, write reference implementations, and build benchmark proofs, but it should not pretend the library is real before the language can enforce the promises on the page.
The standard library has to be treated as part of the language design, not a bag of useful helpers.
Hum's standard library should expose intent first and implementation second.
A programmer should say what semantic contract they need:
store sessions: map SessionId -> Session {
expects:
up to 20 million active sessions
optimizes:
lookup speed
memory density
collision resistance
protects:
attacker cannot force unbounded probe chains
needs:
stable addresses are not required
}
The compiler and stdlib can then choose or reject an implementation:
- dense hash table
- ordered B-tree map
- arena-backed map
- cache-semantic table
- pointer-stable node map
- concurrent sharded map
- GPU-backed table for batched workloads
This is how Hum avoids C++'s problem of making the user manually know 50 subtly different container tradeoffs before they can store data.
See OPTIMIZATION_AND_DSA_STRATEGY.md for the research intake pipeline and optimization admission gate.
See PAVED_ROAD_DOCTRINE.md for the default-path philosophy, STDLIB_CONSTITUTION.md for stable std admission rules, and STDLIB_PRIMITIVE_RESEARCH_2026.md for the first primitive research sweep.
Andrew Krapivin, Martin Farach-Colton, and William Kuszmaul showed in 2025 that open addressing without reordering can do better than older theory suggested. That is a serious signal, but not an immediate drop-in stdlib map.
See HASH_TABLE_RESEARCH_2501_02305.md for the detailed Hum research note.
Hum should create a map-lab benchmark track for hash-table research:
- SwissTable/hashbrown-style dense baseline
- secure/adversarial hashing baseline
- stable low-associativity tables
- open-addressing-without-reordering experiments
- elastic-hashing-inspired insert-heavy experiments
- funnel-hashing-inspired greedy experiments
- cache-semantic GPU tables for batched workloads
The default Map must be safe under hostile input. A faster but HashDoS-weak
map can exist only when the source says the keys are trusted.
Krapivin's 2026 cardinality-constraint work matters more for Hum's verifier than
for ordinary user containers. Smaller CNF encodings and grid-compression-style
ideas can help hum prove generate tighter obligations for needs:, ensures:,
and keeps:.
This belongs in the compiler/prover toolchain before it belongs in the user stdlib.
HierarchicalKV shows a key lesson: some tables should have cache semantics, not dictionary semantics. A full table can evict or reject by policy instead of rehashing or failing.
Hum should make that semantic distinction visible:
store embeddings: cache FeatureId -> Vector {
capacity:
80 GB device memory
evicts:
lowest score first
optimizes:
batched lookup throughput
stable full-capacity performance
}
But this should not be in core v0. GPU-backed structures are powerful and easy to
get wrong. They need a separate std.accel tier.
CHERI is the most important hardware direction to respect. It extends ISAs with capabilities for fine-grained memory protection and compartmentalization.
Hum should not depend on CHERI, but its pointer, FFI, allocator, and unsafe models should be capable of mapping onto CHERI-like hardware later. That means:
- capabilities should be explicit in the type/effect system
- FFI should have visible trust boundaries
- unsafe code should carry
needs:,protects:, andproves:blocks - allocators should preserve provenance and bounds information when possible
C++26 adds library pieces Hum should study: SIMD, inplace vectors, hive-like containers, linear algebra, RCU, hazard pointers, execution control, contracts, and reflection.
The warning is that bolting features onto an old language creates complexity. The menu is useful: these are real systems needs, and Hum should design them as first-class intent-aware APIs instead of afterthought headers.
No heap, no IO, no hidden panics.
Should include:
- primitive types
Bool, integers, floats, checked arithmetic, saturating arithmeticOption,Result- slices, spans, ranges
- fixed arrays
- bit operations
- comparison, hashing traits/capabilities
- compile-time constants
Memory policy is a systems-language feature, not an implementation detail.
Should include:
- global allocator interface
- arena allocator
- bump allocator
- slab allocator
- pool allocator
- page allocator
- secure zeroing allocator
- fallible allocation by default in low-level contexts
- allocation telemetry hooks
Default data structures should optimize for cache locality, memory density, and clear contracts.
Starter set:
VecInlineVecSmallVecDequeMapSetOrderedMapOrderedSetBitSetBloomFilterGraphStableGraphTextBytes
The standard library should prefer flat/dense storage where pointer stability is not required. Pointer stability should be a declared requirement, not an accidental default.
Concurrency primitives need contracts, cancellation, and memory reclamation.
Should include:
- mutexes and read-write locks
- atomics with named memory-order intent
- channels
- structured tasks
- cancellation tokens
- RCU
- hazard pointers
- epoch reclamation
- lock-order declarations
IO should be capability-based and effect-visible.
Should include:
- files
- paths
- streams
- sockets
- buffered IO
- async IO adapters
- deterministic replay hooks
A task that touches IO should say so in uses:.
Cryptography must be misuse-resistant, boring, and strongly typed.
Should include:
- secure random
- hashes
- MACs
- AEAD encryption
- key derivation
- constant-time comparisons
- secret memory wrappers
Do not expose footgun primitives as the default path. Crypto should have a paved road for ordinary secure use, not a tray of sharp primitives with equal status.
Parsing deserves first-class support because agents, compilers, protocols, and security-sensitive systems all need it.
Should include:
- zero-copy parsing
- arena-backed AST construction
- binary protocol primitives
- UTF-8 validation
- bounded input contracts
- structured errors
- fuzz target generation
Hardware features should be portable by default and explicit when specialized.
Should include:
- portable vector types
- CPU feature detection
- runtime dispatch
- cache-line constants
- alignment tools
- prefetch hints only behind measured APIs
- hardware counter/profiling hooks
Hum should never make users write five copies of a loop just to get SSE, AVX, NEON, SVE, or RISC-V Vector support.
Accelerators should be a separate tier.
Possible future modules:
- GPU buffers
- GPU maps/caches
- batched kernels
- tensor and linear algebra adapters
- device/host transfer contracts
This should be built after the CPU semantics are solid.
Before implementing containers, write the rules:
- every stdlib API has a contract
- every allocation is declared or inferred into an allocation effect
- every unsafe block has proof obligations
- every optimized structure has a reference implementation
- every performance claim has a static cost contract, benchmark, or explicit reason it cannot be checked
- every security-sensitive API has misuse tests
- every data structure documents pointer stability, iteration order, memory use, and adversarial behavior
- every structure-facing API passes the optimization and DSA admission gate
- every primitive names its paved-road default and any explicit side roads
Use Rust first.
That is not a betrayal of Hum. It is discipline. Rust gives us memory safety, benchmarks, fuzzing, and real performance while Hum's compiler is still forming.
Each primitive gets:
- Hum-facing API sketch
- Rust reference implementation
- property tests
- fuzz targets
- benchmark suite
- competitor baselines
- design note with tradeoffs
Create .hum examples that express desired stdlib contracts before they compile.
These fixtures drive the parser, semantic graph, effect checker, and test generator.
Once the compiler has enough semantic information, make store declarations
choose strategies.
Example:
store users: map UserId -> User {
expects:
millions of entries
needs:
stable addresses are required
optimizes:
lookup speed
memory density
}
The compiler should be allowed to say:
error: stable addresses conflict with selected dense map strategy
help: use pointer-stable map, arena-backed values, or remove stable-address need
Only after the language is strong enough should core library pieces move into Hum itself.
The first self-hosted targets should be small and proof-friendly:
OptionResult- slices
- checked arithmetic
InlineVec- simple
Mapinterface over a host implementation
Activation note: this discipline turns on once real Hum programs are writable -- that is, once enough stdlib primitives and an execution path exist to build the programs below. Until then it is recorded doctrine, not an active loop. Design work reveals logical inconsistencies; building real programs reveals everything else -- awkward APIs, missing operations, accidental allocations, unclear ownership, weak diagnostics, performance cliffs, path/text confusion, and features that composed badly outside isolation. The stdlib grows from that evidence, not from taste.
An abstraction earns a wider home by how many independent programs need it, not by how elegant it looks. This complements, and does not replace, the compiler-ready rule that a library line needs two independent consumers.
- one program needs it: keep it local to that program;
- two unrelated programs need it: make an experimental package;
- several independent programs need the same abstraction and its semantics
are settled: consider stable
std, subject to STDLIB_CONSTITUTION.md and the benchmark rules below; - only the compiler needs it: keep it in
compiler.support.
Do not promote a helper into std on first sight. Premature promotion is
how a tiny language grows a huge stdlib by accident (see Brutal Critiques 5).
Build a small real program, then: record the friction; classify it as a language, stdlib, tooling, or merely application-specific need; fix the smallest correct layer; and rerun the earlier programs to catch regressions. Friction is triaged through the existing friction ledger and three-strike rule, not fixed ad hoc. Distinguish a genuine architectural flaw from ordinary friction: one awkward call site is not a verdict; repeated workarounds, hidden effects, unsafe escape hatches, or several programs fighting the same abstraction are. Revising an earlier decision under that evidence is healthy, not failure.
Build deliberately different kinds of programs, because each stresses a different part of the language. In rough order of increasing demand:
- a command-line file processor;
- a formatter or linter;
- a package/build tool;
- a structured-data parser and serializer;
- a long-running service (later);
- a constrained, embedded-style state machine;
- eventually, the Hum compiler itself.
A good stdlib is not one with no future changes; additions must be possible without breaking existing users. It is one whose foundational promises are trustworthy: ownership and invalidation are predictable; effects and allocation are visible; paths and text are not confused; failures preserve their causes; common operations are ergonomic; performance is measurable; and APIs work across supported platforms. Those promises are the north star of promotion; the benchmark rules below are how a candidate proves it earns its place.
Source: this section is the triaged, non-duplicative remainder of external dogfooding advice reviewed 2026-07-15. Its interop-first, port-the-problem, and vetted-bindings guidance is deliberately omitted here because it already lives in EXTERNAL_ADVICE_REVIEW.md, INTEROP_AND_PORTABILITY.md, and ADOPTION_STRATEGY_2026.md. Advice is input, not authority.
No stdlib structure should enter std because it is elegant.
It enters because it wins or because it is the safest clear default.
Benchmark against:
- Rust standard library
hashbrown- Abseil containers
- C++ standard library containers
- Folly where relevant
- Zig standard library where relevant
- Go standard library where relevant
- domain-specific research prototypes where relevant
Measure:
- wall-clock time
- memory bytes per element
- allocations per operation
- insertion probes
- present-key lookup probes
- missing-key lookup probes
- tail latency at high load factors
- cache misses
- branch misses
- compile time
- binary size
- adversarial input behavior
- deterministic replay behavior
- "Simpler than Python, faster than Rust" is a slogan, not a design. We only earn it by narrowing choices and making the compiler enforce intent.
- The stdlib cannot chase every new paper. Research becomes standard only after it survives benchmarks, adversarial testing, maintenance, and explanation.
- Natural-language
does:is dangerous if it is executable too early. The compiler needs a small, precise core language underneath the readable surface. why:andwatch for:are only revolutionary if tools consume them. If they become comments, Hum loses its reason to exist.- A tiny language with a huge magical stdlib is still a huge language. Keep the core small, make tiers explicit, and let advanced modules prove themselves.
- Do not promise double or triple RAM. Promise measurable memory density, allocation visibility, and data-structure choices that avoid waste.
- Do not make AI correctness part of the trusted base. Agents can propose; compiler, tests, proofs, and benchmarks decide.
- Use STDLIB_CONSTITUTION.md as the admission gate.
- Create
examples/stdlib/*.humsemantic fixtures for the first primitive set. - Build fixtures for
Result/Option,Vec/Slice/Span,Map/Set, andText/Bytes. - Build a Rust benchmark lab for Map strategies.
- Define the JSON schema for stdlib contract diagnostics.
- Add hum std explain Map as a future tool goal.
- Create the
map-labbenchmark track described in OPTIMIZATION_AND_DSA_STRATEGY.md.
- Krapivin, Farach-Colton, Kuszmaul, "Optimal Bounds for Open Addressing Without Reordering": https://arxiv.org/abs/2501.02305
- Krapivin, Przybocki, Subercaseaux, "Near-Optimal Encodings of Cardinality Constraints": https://arxiv.org/abs/2603.28954
- HierarchicalKV GPU cache-semantic hash table: https://arxiv.org/abs/2603.17168
- CHERI project overview, University of Cambridge: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/
- PICASSO colored capabilities for CHERI temporal safety: https://arxiv.org/abs/2602.09131
- PoisonCap for CHERI temporal and initialization safety: https://arxiv.org/abs/2605.13210
- CHERI-D object IDs for temporal safety: https://arxiv.org/abs/2606.19055
- Abseil container guide: https://abseil.io/docs/cpp/guides/container
- Rust hashbrown README: https://github.com/rust-lang/hashbrown
- C++26 library overview: https://en.cppreference.com/cpp/26
- Hum stdlib constitution: STDLIB_CONSTITUTION.md
- Hum stdlib primitive research sweep: STDLIB_PRIMITIVE_RESEARCH_2026.md