use std::fmt::{Debug, Display}; use supply::prelude::*; use supply::provide::ProvideTag; trait Error: Debug + Display + for<'r> ProviderDyn<'r> {} impl ProviderDyn<'r>> Error for T {} #[derive(Debug)] struct MyError { count: i32, } impl Display for MyError { fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { todo!() } } impl<'r> Provider<'r> for MyError { type Lifetimes = l!['r]; // From core::error::Error: // // fn provide<'a>(&'a self, request: &mut Request<'a>) { ... } fn provide(&'r self, want: &mut dyn Want) { want.provide_value(self.count); } // Something the std Error can't do. fn provide_mut(&'r mut self, want: &mut dyn Want) { want.provide_value(&mut self.count); } } fn log(e: &mut E) -> String { if let Some(count) = e.request_mut::<&mut i32>() { *count += 1; } if let Some(count) = e.request::() { return format!("count: {count}"); } format!("{e:?}") } #[test] fn custom_error() { let mut my = MyError { count: 42 }; let e: &mut dyn Error = &mut my; assert_eq!(log(e), "count: 43"); assert_eq!(log(e), "count: 44"); let mut x = 123; let e: &mut dyn Error = ProvideTag::from_mut(&mut x); assert_eq!(log(e), "ProvideTag(124)"); assert_eq!(log(e), "ProvideTag(125)"); } struct Error2 { a: i32, b: i32, } // supply replaces the would_be_satisfied functions with the try_for_id and WantFor impl<'r> Provider<'r> for Error2 { type Lifetimes = l![]; fn provide(&'r self, want: &mut dyn Want) { // Check that the want will accept a value of i32 before doing out "expensive" operation. if let Some(want) = want.try_for::() { want.fulfill(self.a + self.b); } } } #[test] fn error_2() { let e = Error2 { a: 1, b: 4 }; assert_eq!(e.request::().unwrap(), 5); assert!(e.request::().is_none()); }