Skip to content

anyhow!: keep the error chain when converting Arc<Error> - #465

Open
Sanjays2402 wants to merge 1 commit into
dtolnay:masterfrom
Sanjays2402:fix-arc-error-chain
Open

Sanjays2402 wants to merge 1 commit into
dtolnay:masterfrom
Sanjays2402:fix-arc-error-chain

Conversation

@Sanjays2402

Copy link
Copy Markdown

Fixes #405.

An anyhow::Error held behind an Arc does not implement std::error::Error (it only derefs to a dyn Error), so anyhow!(arc) matched neither the TraitKind nor the BoxedKind arm and fell through to the message-only path. The result kept only the outermost context: printing with {:#} showed just "error2", source() returned None, and chain() had a single entry, even though the wrapped error still carried "error1" underneath.

This adds a SharedKind dispatch arm for Arc that wraps it transparently and delegates source() to the inner error's chain, so {:#} prints "error2: error1", source() returns the "error1" error, and chain() walks the full chain again. Downcasting to Arc, by reference and by value, keeps working exactly as it did through the old message-only path.

There is deliberately no From<Arc> impl here: the compiler rejects it as conflicting with the blanket From impl, since std could one day provide an Error impl for Arc wrappers of anyhow::Error. For the same reason, a borrowed &'static Error (issue #341) cannot be covered by this dispatch: AdhocKind's blanket impl for &T already applies to it with the same receiver, so a dedicated arm would make the macro call ambiguous. That case still goes through the old message-only path.

Tests: added test_anyhow_from_arc_error_keeps_chain and test_anyhow_from_arc_error_downcast_by_value to tests/test_convert.rs. Both failed on the old code (chain of length 1, source None) and pass now. The full suite passes (cargo test), along with cargo fmt --check, cargo check --no-default-features, and cargo clippy --tests.

An anyhow::Error behind an Arc does not implement std::error::Error, so
anyhow!(arc) fell through to the message-only path and kept only the
outermost context, dropping every cause below it. This adds a SharedKind
dispatch arm that wraps the Arc transparently and delegates source() to
the inner error's chain, so display, alternate display, source() and
chain() all see the full chain again. Downcasting to Arc<Error>, by
reference and by value, keeps working as before.

Fixes dtolnay#405.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Creating anyhow! from Arc<Error> miss error source

1 participant