Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add displaydoc crate to derive fmt::Display for SignalProtocolError #296

Merged
merged 1 commit into from Oct 8, 2021

Conversation

cosmicexplorer
Copy link
Contributor

@cosmicexplorer cosmicexplorer commented May 9, 2021

Problem

I looked into @jrose-signal's comment #287 (comment) comparing the use of thiserror vs adding real docstrings as in #287. I believe they are totally orthogonal.

With that in mind, it looks like displaydoc might be able to just save some of our boilerplate in error.rs.

Solution

  1. Import displaydoc::Display and add docstrings to every case of SignalProtocolError to auto-derive fmt::Display.

Result

Our fmt::Display implementation for SignalProtocolError requires less code because we can rely on a macro to derive it! We also end up adding a first pass of documentation to all of our error cases!

@simonsan
Copy link

simonsan commented May 9, 2021

https://crates.io/crates/displaydoc might come handy as well. ;)

@jrose-signal
Copy link
Contributor

Right, we've previously had a PR to switch to thiserror and decided that the boilerplate savings weren't worth the additional dependency and DSL. displaydoc pushes my thoughts back in the other direction because they become (sparse) doc comments as well.

@cosmicexplorer
Copy link
Contributor Author

Got it! I'll try out displaydoc! Might steal from #287!

@cosmicexplorer
Copy link
Contributor Author

Ok, redone to use displaydoc! Note that we still depend on thiserror for the Error derive macro with the #[from] and #[source] annotations.

@cosmicexplorer cosmicexplorer changed the title add thiserror crate to derive fmt::Display for SignalProtocolError add displaydoc crate to derive fmt::Display for SignalProtocolError May 13, 2021
use std::fmt;
use std::panic::UnwindSafe;

pub type Result<T> = std::result::Result<T, SignalProtocolError>;

/// Wraps a boxed error struct and delegates the [std::error::Error] trait to it.
///
/// A [Box] wrapping an error apparently does not implement [std::error::Error] itself, which breaks
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, that implementation is in the stdlib. Something else must be going on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, there is a distinction between Box<E: Error> and Box<dyn Error>. I have added this explanatory link to the docstring: https://stackoverflow.com/a/62452516/2518889.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe we could work around this by adding a type parameter E: Error to the definition of SignalProtocolError, but that seems like it would make instantiating SignalProtocolError even more annoying than wrapping in CallbackErrorWrapper.

Comment on lines 16 to 26
/// Wraps a boxed error struct and delegates the [std::error::Error] trait to it.
///
/// Unlike a `Box<E: Error>` wrapping a concrete error type, a `Box<dyn Error>` wrapping
/// a type-erased trait object does *not* implement [std::error::Error] itself (see [this
/// stackoverflow answer] for details). This breaks the ability to nicely use the `#[source]`
/// annotation from the [thiserror::Error] derive macro. In order to avoid manually impling
/// [std::error::Error::source] for each case of [SignalProtocolError], we create this wrapper
/// struct to delegate to the underlying `dyn Error` in order to nicely derive [thiserror::Error]
/// for [SignalProtocolError::ApplicationCallbackError].
///
/// [this stackoverflow answer]: https://stackoverflow.com/a/62452516/2518889
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think the resulting code is clearer than just implementing source manually (and therefore Error). In the choice between making one place a lot more complicated and many places a little more complicated, I'd usually err on the side of containing the complexity. (If only we didn't need UnwindSafe here.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you so much for investigating where that might be added to thiserror! I have removed the thiserror dependency for now along with CallbackErrorWrapper until we can avoid making many places a little more complicated as described.

@cosmicexplorer cosmicexplorer force-pushed the thiserror-attempt branch 2 times, most recently from 3980aab to 0a76d24 Compare October 8, 2021 03:21
- remove thiserror for now until we can derive UnwindSafe
@jrose-signal
Copy link
Contributor

Okay, the Java failure is our fault for me coincidentally picking a bad nightly, rust-lang/cargo#9919, so I'll merge this anyway.

@jrose-signal jrose-signal merged commit baaa684 into signalapp:master Oct 8, 2021
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.

None yet

3 participants