Skip to content

feat(error): add shared bail! and ensure! macros to ironrdp-error#1263

Merged
Benoît Cortier (CBenoit) merged 2 commits into
Devolutions:masterfrom
lamco-admin:feat/ironrdp-error-bail-ensure-macros
May 12, 2026
Merged

feat(error): add shared bail! and ensure! macros to ironrdp-error#1263
Benoît Cortier (CBenoit) merged 2 commits into
Devolutions:masterfrom
lamco-admin:feat/ironrdp-error-bail-ensure-macros

Conversation

@glamberson
Copy link
Copy Markdown
Contributor

Refs #1257.

Implements Change 3 from the proposal in #1257. Adds workspace-shared bail! and ensure! macros to ironrdp-error so call-site verbosity for typed errors matches anyhow::bail!/anyhow::ensure!.

What changes

  • bail!(kind) — empty context.
  • bail!(context, kind) — explicit &'static str context.
  • bail!(context, kind, source: source) — explicit context plus a chained source error.
  • ensure!(condition, kind) — empty context.
  • ensure!(condition, context, kind) — explicit context.

Both macros are #[macro_export]ed at the ironrdp-error crate root and use $crate::Error::new(...) for hygiene. The kind type is inferred from the enclosing function's return type (which must be Result<_, Error<Kind>> or any alias resolving to it).

Composition with #[track_caller]

Once Change 2 (#1262) lands and Error::new is annotated #[track_caller], these macros automatically capture the location at the macro use site (because the Error::new call expanded inside the macro is the caller of its own constructor, and #[track_caller] resolves to the macro's caller). This is the intended composition: Change 2 supplies the location, Change 3 supplies the call-site ergonomics, both compose without coordination.

No deprecation of per-crate macros

The existing per-crate constructor macros (decode_err!, encode_err!, pdu_other_err!, etc.) serve a different ergonomic pattern: they construct an error to be passed to ? or .map_err(...), rather than performing an early return. The shared bail!/ensure! are additive — they cover the early-return patterns that previously required hand-written return Err(Error::new(...)) boilerplate. The per-crate constructor macros remain useful for .map_err(decode_err!(...)) style and are not deprecated by this change.

Public API impact

Strictly additive. Two new exported macros at the ironrdp-error crate root. No changes to existing types, traits, or methods.

no_std verification

All three feature combinations of ironrdp-error build cleanly:

  • cargo check -p ironrdp-error --no-default-features
  • cargo check -p ironrdp-error --no-default-features --features alloc
  • cargo check -p ironrdp-error --features std

The macros use only fully-pathed std-free constructs (::core::result::Result::Err, $crate::Error::new), so they work identically across feature combinations.

xtask verification

  • cargo xtask check fmt: clean
  • cargo xtask check lints: clean
  • cargo xtask check locks: clean
  • cargo xtask check typos: clean
  • cargo xtask check tests: clean

Diff size

1 file changed, +56 lines, no deletions.

Refs Devolutions#1257.

Implements Change 3 from the proposal in Devolutions#1257. Adds workspace-shared
`bail!` and `ensure!` macros to ironrdp-error so call-site verbosity for
typed errors matches anyhow::bail!/anyhow::ensure!.

### What changes

- `bail!(kind)` — empty context.
- `bail!(context, kind)` — explicit `&'static str` context.
- `bail!(context, kind, source: source)` — explicit context plus a chained
  source error.
- `ensure!(condition, kind)` — empty context.
- `ensure!(condition, context, kind)` — explicit context.

Both macros are `#[macro_export]`ed at the ironrdp-error crate root and use
`$crate::Error::new(...)` for hygiene. The kind type is inferred from the
enclosing function's return type (which must be `Result<_, Error<Kind>>` or
any alias resolving to it).

### Composition with #[track_caller]

Once Change 2 (Devolutions#1262) lands and `Error::new` is annotated `#[track_caller]`,
these macros automatically capture the location at the macro use site
(because the `Error::new` call expanded inside the macro is the caller of
its own constructor, and `#[track_caller]` resolves to the macro's caller).
This is the intended composition: Change 2 supplies the location, Change 3
supplies the call-site ergonomics, both compose without coordination.

### No deprecation of per-crate macros

The existing per-crate constructor macros (`decode_err!`, `encode_err!`,
`pdu_other_err!`, etc.) serve a different ergonomic pattern: they construct
an error to be passed to `?` or `.map_err(...)`, rather than performing an
early return. The shared `bail!`/`ensure!` are additive — they cover the
early-return patterns that previously required hand-written
`return Err(Error::new(...))` boilerplate. The per-crate constructor
macros remain useful for `.map_err(decode_err!(...))` style and are not
deprecated by this change.

### Public API impact

Strictly additive. Two new exported macros at the ironrdp-error crate root.
No changes to existing types, traits, or methods.

### no_std verification

All three feature combinations of ironrdp-error build cleanly:
- `cargo check -p ironrdp-error --no-default-features`
- `cargo check -p ironrdp-error --no-default-features --features alloc`
- `cargo check -p ironrdp-error --features std`

The macros use only fully-pathed std-free constructs (`::core::result::Result::Err`,
`$crate::Error::new`), so they work identically across feature combinations.

### xtask verification

- `cargo xtask check fmt`: clean
- `cargo xtask check lints`: clean
- `cargo xtask check locks`: clean
- `cargo xtask check typos`: clean
- `cargo xtask check tests`: clean
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds workspace-shared early-return error macros to ironrdp-error to reduce call-site boilerplate while preserving typed Error<Kind> usage across the workspace.

Changes:

  • Introduces bail! macro (with optional context and optional source: chaining via with_source).
  • Introduces ensure! macro (with optional context) for condition checks with early-return typed errors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ironrdp-error/src/lib.rs Outdated
Comment thread crates/ironrdp-error/src/lib.rs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants