Make WorkTable's own source std-free - #101
Closed
pathscale wants to merge 3 commits into
Closed
Conversation
Around 170 of WorkTable's std:: paths name something core or alloc provides outright: fmt, mem, hash, marker, cmp, ops, iter, num, ptr, hint, any, array, future, pin, task, cell, error, atomics, Arc, Rc, Duration, VecDeque and the BTrees. Those are a rename, and doing them first leaves only the paths that genuinely want an operating system, which is the list worth arguing about. Hash maps move to hashbrown, which is what std's own HashMap is built on. Two consequences are real rather than mechanical. hashbrown's `get` is bounded on Equivalent<K> where std's is bounded on Borrow<Q>, so a key written as `&1.into()` no longer infers and now names its type. And `BatchData` is a public type alias, so a caller building one with std::collections::HashMap has to say worktable::prelude::HashMap instead; the prelude re-exports it. Generated code cannot name alloc or hashbrown, since a user crate has neither in scope, so it goes through the prelude, and WorkTable gains a `extern crate self as worktable` alias so those paths also resolve in the crate that emits them. The stripe hasher becomes rustc_hash's, already a dependency, because hashbrown does not carry DefaultHasher. 926 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`#![cfg_attr(not(feature = "std"), no_std)]` behind a default-on `std` feature, so the crate builds exactly as before unless a caller asks for otherwise, and `cargo check --no-default-features` now measures whether WorkTable's own source needs an operating system. Without std, Vec, String, Box, ToString, ToOwned, vec! and format! leave the prelude, which was 528 of the 550 errors that flip produced. Each module now names what it uses from alloc; the two macros come from a `#[macro_use] extern crate alloc`. Nothing else changed, which is why the same 926 tests pass unmoved. Four files take Box without writing it: `#[async_trait]` and `worktable!` both expand to `Box<dyn Future>`. Spinning code that gave up its timeslice with `std::thread::yield_now` goes through `util::yield_now`, which is that call under std and the spin hint without one, there being no scheduler to yield to. 22 errors remain, every one of them in the persistence half. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
WorkTable's own source now compiles with `--no-default-features`, with no errors and no warnings. The default build is unchanged and the same 926 tests pass. The line is not where the module tree suggested. `persistence` looked like the std half wholesale, but the table's own mutation path builds `Operation` values inline, so gating the module took the insert path with it. Those types are plain data: `operation` and `operation::util` name no std path, no filesystem and no runtime, so they stay in the core, and the gate falls on what actually wants an operating system: `engine`, `error` (which is a path and a reason), `space`, `task`, `readonly_engine`, `operation::batch`, and the `PersistenceEngine` trait that speaks in batches. `vacuum` goes with them. It needs `Instant` for its settle deadline and `PersistenceResult` for its trait, and a table with no background runtime has nothing to run a defragmenter on. The support surface it alone calls follows it: the live-cell counters, the vacuum row move, and the ART topology export. Also gated: `WorkTable::validate_persisted_state`, which audits a loaded file and so takes a `Path`; the `WorkTableError::Persistence` variant; the `MemStat` impls for `SystemTime` and `Instant`; and `migration`, which opens files. This does not make the crate build for a bare-metal target. Its dependencies still want std, and arc-swap, parking_lot and data_bucket are each their own piece of work. What it does establish is that none of the remaining distance is WorkTable's own code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Owner
Author
|
Superseded by #102, which contains every commit on this branch: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
cargo check --no-default-featuresnow passes with no errors and no warnings. The default build is unchanged and the same 926 tests pass.What the numbers were
Counting
std::paths in the source predicts nothing useful, so the work was driven by the compiler instead. Flipping#![no_std]on produced 550 errors. They fell into three groups of very different character:fmt,mem,hash,marker,cmp,ops,iter,num,ptr,hint,any,array,future,pin,task,cell,error, atomics,Arc,Rc,Duration,VecDeque, the BTreesVec356,String68,vec!47,format!41,Box26Where the line actually falls
Not where the module tree suggested.
persistencelooked like the std half wholesale, but the table's own mutation path buildsOperationvalues inline, so gating the module took the insert path with it. Those types are plain data:operationandoperation::utilname no std path, no filesystem and no runtime, and they stay in the core.The gate falls on what wants an operating system:
engine,error(which is a path and a reason),space,task,readonly_engine,operation::batch, and thePersistenceEnginetrait that speaks in batches.vacuumgoes with them, needingInstantfor its settle deadline andPersistenceResultfor its trait; a table with no background runtime has nothing to run a defragmenter on.Also gated:
validate_persisted_state(audits a loaded file, so takes aPath), theWorkTableError::Persistencevariant, theMemStatimpls forSystemTimeandInstant, andmigration.Two changes that are not mechanical
Hash maps move to
hashbrown, which is whatstd's ownHashMapis built on. Itsgetis bounded onEquivalent<K>wherestd's is bounded onBorrow<Q>, so a key written&1.into()no longer infers and now names its type.BatchDatais a public alias, so a caller building one withstd::collections::HashMapmust sayworktable::prelude::HashMap; the prelude re-exports it.Generated code cannot name
allocorhashbrown, since a user crate has neither in scope, so it goes through the prelude, and the crate gains anextern crate self as worktablealias so those paths also resolve where they are emitted.What this does not do
It does not make the crate build for a bare-metal target.
arc-swaphas nostdfeature at all, ourparking_lotfork deliberately drops the generic thread parker, anddata_bucketis its own piece of work. Each was measured separately by building it as its own#![no_std]crate foraarch64-unknown-none.What it establishes is that none of the remaining distance is WorkTable's own code.
🤖 Generated with Claude Code