Repository navigation
Drop third-party dependencies from the default build (v1.1.0) - #17
Open
jamesgober wants to merge 2 commits into
Open
jamesgober wants to merge 2 commits into
jamesgober wants to merge 2 commits into
Conversation
added 2 commits
October 14, 2026 05:13
With default features error-forge pulled eight third-party crates into every dependent's build (pastey, parking_lot, lock_api, parking_lot_core, scopeguard, smallvec, cfg-if, and windows-link or libc). The 14 local dependents use only the ForgeError trait. Both always-on dependencies are gone; the default graph is now error-forge plus its own error-forge-derive, with no third-party crate on any target. pastey: define_errors! needs it only to lowercase variant names into constructor names, which macro_rules cannot do. error-forge-derive now carries a small proc macro for that, written against proc_macro alone (error_forge::__private::paste!, not public API). Its syn, quote and proc-macro2 dependencies move behind a new default-on `derive` feature, and error-forge depends on it with default features off, so the derive still costs nothing unless enabled. The error-forge-derive feature that Cargo used to create implicitly is declared explicitly with the same meaning; cargo semver-checks against 1.0.2 passes all 196 checks. Constructor names, spans and keyword errors match pastey. parking_lot: CircuitBreaker now uses std::sync::Mutex and takes it through PoisonError::into_inner, so no method can panic on a poisoned lock, as before. A successful closed-state call no longer takes the lock a second time in on_success, which only acts on the half-open probe. Against 1.0.2, execute is 17% (Windows) / 20% (Linux) faster uncontended and 47% / 10% faster with eight threads on one breaker. With identical single-lock code parking_lot is within 1 ns uncontended, about 20 ns/call faster contended on Linux and 80 ns slower on Windows. A clean debug build of a default-features dependent drops from 1.09 s to 0.78 s wall (32 jobs) and 2.67 s to 0.99 s on one job. CI gains a gate that fails if the default dependency graph of error-forge contains a third-party crate on any target. STABILITY.md, architecture.md, COMPARISON.md, migration.md, SECURITY.md and the README describe the new dependency set; STABILITY.md narrows its dependency rules to what dependents can observe.
Bump error-forge and error-forge-derive to 1.1.0, require error-forge-derive 1.1.0, and point the README install snippet at 1.1.0. The CHANGELOG entry stays under [Unreleased] until the release is approved and dated.
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.
Do not merge, tag or publish yet: owner decisions needed (see below).
Summary
With default features, error-forge pulled 8 third-party crates into every dependent's normal build, while the dependents (throttle-net, rate-net, better-bucket and the rest) use only the
ForgeErrortrait. Both always-on dependencies are now gone. The default graph iserror-forgeplus its ownerror-forge-derive, which has no dependencies of its own. No public item was added to, removed from or changed inerror-forge, anddefault = []is unchanged.define_errors!constructor names (fn [<$variant:lower>])pasteyerror-forge-deriveonproc_macroalone (error_forge::__private::paste!, internal).syn/quote/proc-macro2move behind a new default-onderivefeature of the derive crate;error-forgedepends on it with default features offrecovery::CircuitBreakerinternal stateparking_lot,lock_api,parking_lot_core,scopeguard,smallvec,cfg-if,windows-link/libcstd::sync::MutexviaPoisonError::into_inner, so it still never panics. The success path now takes the lock once instead of twiceAll other third-party deps (
serde,log,tracing,async-trait,rand, andsynforderive) were already behind opt-in features and are unchanged.Evidence
cargo tree -p error-forge -e normal, default features, excluding selferror-forge-derive, 0 deps)Clean debug build of a dependent (Windows,
CARGO_INCREMENTAL=0, median of 5):-j321.09 s → 0.78 s;-j12.67 s → 0.99 s.CircuitBreaker::execute(release, no-op closure, ns per call):Uncontended, std and parking_lot are equal. Under heavy synthetic contention parking_lot is about 20 ns/call better on Linux and about 80 ns/call worse on Windows. Next to the I/O a breaker guards, neither difference matters, so it doesn't meet the "necessary and measurably better" bar. Compared with 1.0.2, the branch is faster everywhere.
Gates
cargo fmt --all -- --check-D warningson 1.95 and 1.99: all-features, default, no-default, derive crate aloneerror-forge-derive,async log tracing jitter, and all-features (140, incl. trybuild UI) on Windows 1.95. Linux 1.99 all-features: 140RUSTDOCFLAGS=-D warnings cargo doccargo audit --deny warningsclean;cargo deny checkok (same warnings as main)cargo semver-checks -p error-forge --baseline-version 1.0.2: 196 pass, no semver update required. The tool can't check proc-macro crates, soerror-forge-derivewas reviewed by hand: it only adds a default-onderivefeature and a hidden macrocargo publish --workspace --dry-run: both crates package and verify--target all)New tests:
tests/paste_test.rscovers constructor naming (acronyms,r#variants, non-ASCII, digits) and the macro's modifiers and nesting.tests/ui/fail/paste_bad_modifier.rscovers each error path. ATypevariant gives the sameexpected identifier, found keyworderror as 1.0.2 (checked against the published crate).Decisions needed from the owner
error-forge-derivegoes from optional to always-on. VERSIONING.md, which is authoritative across the portfolio, classes neither change as breaking: the "would user code still compile?" test passes, and semver-checks agrees. The 1.0.2 removal ofthiserrorset the same precedent. This PR narrows those clauses to third-party dependencies and public-API exposure, with a paragraph explaining why. Please confirm this is MINOR rather than MAJOR.Cargo.lock, so whichever merges second gets a trivial lockfile conflict.After approval, the release steps are: date the CHANGELOG section, tag
v1.1.0, publisherror-forge-deriveand thenerror-forge. Local notes are in.dev/audits/2026-10-14.mdand.dev/release/v1.1.0.md(gitignored).