feat(error): add shared bail! and ensure! macros to ironrdp-error#1263
Merged
Benoît Cortier (CBenoit) merged 2 commits intoMay 12, 2026
Conversation
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
This was referenced May 11, 2026
There was a problem hiding this comment.
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 optionalsource:chaining viawith_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.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Benoît Cortier (CBenoit)
approved these changes
May 12, 2026
68b86f2
into
Devolutions:master
10 checks passed
This was referenced May 12, 2026
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.
Refs #1257.
Implements Change 3 from the proposal in #1257. Adds workspace-shared
bail!andensure!macros toironrdp-errorso call-site verbosity for typed errors matchesanyhow::bail!/anyhow::ensure!.What changes
bail!(kind)— empty context.bail!(context, kind)— explicit&'static strcontext.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 theironrdp-errorcrate root and use$crate::Error::new(...)for hygiene. The kind type is inferred from the enclosing function's return type (which must beResult<_, Error<Kind>>or any alias resolving to it).Composition with
#[track_caller]Once Change 2 (#1262) lands and
Error::newis annotated#[track_caller], these macros automatically capture the location at the macro use site (because theError::newcall 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 sharedbail!/ensure!are additive — they cover the early-return patterns that previously required hand-writtenreturn 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-errorcrate root. No changes to existing types, traits, or methods.no_std verification
All three feature combinations of
ironrdp-errorbuild cleanly:cargo check -p ironrdp-error --no-default-featurescargo check -p ironrdp-error --no-default-features --features alloccargo check -p ironrdp-error --features stdThe 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: cleancargo xtask check lints: cleancargo xtask check locks: cleancargo xtask check typos: cleancargo xtask check tests: cleanDiff size
1 file changed, +56 lines, no deletions.