Replace bun_core::Error intern machinery with per-crate thiserror enums
Merged
RO
4mo ago+8058+8058+0123456789012345678901234567890123456789-4927-4927-0123456789012345678901234567890123456789
Replaces the runtime-interned global error set bun_core::Error (#[repr(transparent)] NonZeroU16) and the err!() macro with idiomatic per-crate thiserror enums.
Why
err!(Name) cached a global RwLock<Vec<&'static str>> intern lookup in a per-site AtomicU16. Not a const, so it could never be a pattern; every dispatch was an if-else guard chain with no exhaustiveness check (worst case ~40 arms in FetchTasklet::to_body_value_error). This was Zig's anyerror, ported.
Design
One #[derive(thiserror::Error)] enum per crate at <crate_dir>/error.rs, re-exported as crate::Error + crate::Result<T, E = Error>:
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
pub enum Error {
#[error("TooManyRedirects")]
TooManyRedirects,
#[error(transparent)] Sys(#[from] bun_errno::SystemErrno),
#[error(transparent)] Alloc(#[from] bun_alloc::AllocError),
}
err!("OutOfMemory")(92 sites, 17 crates) routes tobun_alloc::AllocError- errno/fs names (
ENOENT,FileNotFound,AccessDenied,NoSpaceLeft,NameTooLong,NotDir,EISDIR,BadPathName, allE*) route tobun_errno::SystemErrno(2 bytes). NOTbun_sys::Error(40 bytes; the context tier). - Cross-crate duplicate names are intentional:
css::Error::InvalidCharacter!=sql::Error::InvalidCharacter. #[error(transparent)] X(#[from] ...)for pass-through;?composes viaFrom.- Every enum also impls
bun_core::output::ErrNamesoOutput::err(e, ...)keeps working. - Every
#[error("...")]string preserves the originalerr!("...")literal verbatim. - No new deps (
thiserror = "2"was already a workspace dep). Nodyn Error/Box<dyn Error>/anyhow.
Deleted
macro_rules! err+.bun_errlink-section (src/bun_core/lib.rs)SEED,EXTRA,intern_slow,intern_cached,Error::intern,Error::from_errno,Error::from_raw,Error::name,Error::as_u16, theRwLock<Vec<&'static str>>intern table (src/bun_core/result.rs)named_error_set!macro (all 31 call sites deleted; enums now derivethiserror::Errordirectly)OrWriteFailedtraitErrorCode::from(bun_core::Error)/ErrorCode::to_error()(src/jsc/ErrorCode.rs): these aliased the internu16onto the JS error-code table index. Callers ofErrorable::err()now passErrorCode(ErrorCode::JS_ERROR_OBJECT)directly.impl From<bun_sys::Error> for bun_core::Error(src/sys/lib.rs); replaced withFrom<bun_sys::Error> for bun_errno::SystemErrno.
bun_core::Error still exists but is now bun_core's own local 13-variant thiserror enum (for the bun_core::io::Write trait's return type).
Foundation
bun_errno::SystemErrnonow implsDisplay+core::error::Error(viastrum::IntoStaticStr).bun_alloc::AllocErrornow implsDisplay+core::error::Error.
Scope
- 1,641
err!()call sites across 40 crates, 449 distinct names - 523 files changed, +7435 -4331
Verification
cargo check --workspace --keep-going: greencargo build --workspace --keep-going: green (post-mono const asserts)bun run rust:check-all: green across all 10 targets (linux/macos/windows x x64/aarch64 + android)
Deferred
bun_runtime(192 local variants) andbun_install(117) kept as flat per-crate enums rather than module-level split. Splitting would change==semantics for the 9 names that span modules insidebun_runtime; both enums are still <=4 bytes withSysnesting.- Shrinking
bun_sys::Error(40 bytes), variant payloads,$ERR_*JS machinery: out of scope.