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

Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
This commit is contained in:
Sabrina Jewson 2023-06-22 22:46:39 +01:00 committed by GitHub
parent 8dae97a5e8
commit 3c514ab0b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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) => {