masterror 0.21.1

Application error types and response mapping
Documentation
Цели дизайна

Явные коды и домены
thiserror форматирует сообщение, но не даёт стабильных кодов. Введи:

ErrorCode(NonZeroU32) и ErrorDomain(&'static str).

Инвариант: код стабилен, сообщение и поля — нет.

Диапазоны кодов per-crate/перенейминг через макрос домена.

Прозрачный рантайм: ноль лишних аллокаций

Display строится без format! при конструировании.

Сообщение — &'static str + форматирование аргументов на выводе.

Опциональный Backtrace по фиче, захват один раз при создании.

Минимальный proc-macro

Зависимости только proc_macro2, syn, quote. Никаких reflection-трюков, никаких «скрытых» From на всё подряд.

Атрибуты валидируются жёстко, ошибки — диагностически понятные.

Интероп и миграция

From<anyhow::Error>/Into<anyhow::Error> по фиче.

Маппинг thiserror-стиля: #[source], #[transparent], форматные строки.

Утилиты: chain() итератор по причинам, report() для человекочитаемого трейсинга.

Контекст и структурные данные без глобального стейта

Лёгкий Context как иммутабельный key-value snapshot (SmallVec<[(&'static str, Cow<'static, str>); N]>), без мутабельного глобала.

По фиче serde — сериализация структурных данных.

MSRV/скорость компиляции

MSRV = актуальный LTS/твоя корпоративная, без «танцев» в макросе.

Меньше генерируемого кода: без дублирующих From/Display там, где можно обойтись общими трейтом-адаптерами.

---

Реализация: план работ

core

Трейты MasterError, ErrorCategory, Context, итератор chain(), Report для красивого вывода.

Фичи: backtrace, serde, anyhow, miette.

derive

Парсер атрибутов (только syn/quote).

Проверки: единственный #[source]; запрет transparent вместе с кастомным #[error("…")]; обязательность #[code(..)].

Генерация Display с match, без промежуточных String.

интеграции

impl From<T> for E только по явному #[from].

Into<anyhow::Error> по фиче: сохраняем code/domain в anyhow::Context через newtype-адаптер и downcast_ref.

UX-инструменты

err! и bail! макросы, которые не плодят типы, а создают твой enum? Нет. Оставь это anyhow. Дай макрос ensure!(cond, MyError::X { … }) как удобство, но без магии.

#[deny(masterror::missing_code)] внутренняя диагностическая либа на базе rustc lints через proc_macro_diagnostic для ранней обратной связи.

Документация и примеры

Cookbook: «миграция с thiserror за 15 минут».

Пример с Axum: маппинг на HTTP-статусы по category() и логирование кода/домена.

Выход на прод: чек-лист