Fix .source() of composite rejections (#2030)

Co-authored-by: David Pedersen <[email protected]>
This commit is contained in:
Sabrina Jewson
2023-06-22 23:46:39 +02:00
committed by GitHub
co-authored by David Pedersen
parent 8dae97a5e8
commit 3c514ab0b4
+41 -1
View File
@@ -203,7 +203,7 @@ 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(),
)+
}
}
@@ -211,6 +211,46 @@ macro_rules! __composite_rejection {
};
}
#[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) => {