Skip to content

Commit

Permalink
Fix .source() of composite rejections (#2030)
Browse files Browse the repository at this point in the history
Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
  • Loading branch information
SabrinaJewson and davidpdrsn committed Jul 16, 2023
1 parent 095bf2f commit 16b6388
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion axum-core/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,54 @@ macro_rules! __composite_rejection {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
$(
Self::$variant(inner) => Some(inner),
Self::$variant(inner) => inner.source(),
)+
}
}
}
};
}

#[cfg(test)]
mod composite_rejection_tests {
use self::defs::*;
use crate::Error;
use std::error::Error as _;

#[allow(dead_code, unreachable_pub)]
mod defs {
use crate::{__composite_rejection, __define_rejection};

__define_rejection! {
#[status = BAD_REQUEST]
#[body = "error message 1"]
pub struct Inner1;
}
__define_rejection! {
#[status = BAD_REQUEST]
#[body = "error message 2"]
pub struct Inner2(Error);
}
__composite_rejection! {
pub enum Outer { Inner1, Inner2 }
}
}

/// The implementation of `.source()` on `Outer` should defer straight to the implementation
/// on its inner type instead of returning the inner type itself, because the `Display`
/// implementation on `Outer` already forwards to the inner type and so it would result in two
/// errors in the chain `Display`ing the same thing.
#[test]
fn source_gives_inner_source() {
let rejection = Outer::Inner1(Inner1);
assert!(rejection.source().is_none());

let msg = "hello world";
let rejection = Outer::Inner2(Inner2(Error::new(msg)));
assert_eq!(rejection.source().unwrap().to_string(), msg);
}
}

#[rustfmt::skip]
macro_rules! all_the_tuples {
($name:ident) => {
Expand Down

0 comments on commit 16b6388

Please sign in to comment.