Last active
September 15, 2024 00:24
-
-
Save tesaguri/64bbe8aa010736a84c5fed2bda9946fd to your computer and use it in GitHub Desktop.
Experiment to implement a `Debug`-like trait for any type using specialization.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![feature(specialization)] | |
| // #![feature(min_specialization)] // error: cannot specialize on trait `Debug` | |
| use core::fmt::{self, Debug, Formatter}; | |
| #[test] | |
| #[should_panic( | |
| expected = "called `Result::unwrap_any()` on an `Err` value: playground::unwrap_non_debug::NonDebug" | |
| )] | |
| fn unwrap_non_debug() { | |
| struct NonDebug; | |
| Err::<(), _>(NonDebug).unwrap_any(); | |
| } | |
| #[test] | |
| #[should_panic(expected = "called `Result::unwrap_any()` on an `Err` value: \"hello\"")] | |
| fn unwrap_debug() { | |
| Err::<(), _>("hello").unwrap_any(); | |
| } | |
| pub trait DebugAny { | |
| fn fmt(&self, f: &mut Formatter) -> fmt::Result; | |
| fn force_debug(&self) -> impl Debug { | |
| ForceDebug(self) | |
| } | |
| } | |
| impl<T: ?Sized> DebugAny for T { | |
| default fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
| f.write_str(core::any::type_name::<Self>()) | |
| } | |
| } | |
| impl<T: ?Sized + Debug> DebugAny for T { | |
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
| Debug::fmt(self, f) | |
| } | |
| } | |
| struct ForceDebug<'a, T: ?Sized>(&'a T); | |
| impl<'a, T: ?Sized> Debug for ForceDebug<'a, T> { | |
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
| DebugAny::fmt(self.0, f) | |
| } | |
| } | |
| pub trait UnwrapAnyExt { | |
| type Item; | |
| fn unwrap_any(self) -> Self::Item; | |
| } | |
| impl<T, E: DebugAny> UnwrapAnyExt for Result<T, E> { | |
| type Item = T; | |
| fn unwrap_any(self) -> T { | |
| match self { | |
| Ok(t) => t, | |
| Err(e) => panic!( | |
| "called `Result::unwrap_any()` on an `Err` value: {:?}", | |
| e.force_debug(), | |
| ), | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment