## Error Handling PG Update Jane Lusby --- It's too easy to lose context when reporting ---- Upgrading an Error to a panic! ```rust= fn main() { let _config = load_config() .expect("config is always valid and exists"); } ``` ---- Currently goes through Debug ``` $ cargo run thread 'main' panicked at 'config is always valid and exists: Error(SourceError)', main.rs:4:33 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` ---- We would like it to go through Error ``` $ cargo run thread 'main' panicked at 'config is always valid and exists', src/main.rs:4:33 Error: 0: invalid config 1: config file does not exist note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` ---- Dependencies * <!-- .element: class="fragment" --> Moving the error trait into core * <!-- .element: class="fragment" --> specialize unwrap and expect to pass in source as a &dyn Error * <!-- .element: class="fragment" --> blocked specialization soundness issue with lifetime dependent trait impls * <!-- .element: class="fragment" --> fixed by always applicable impls? --- The Missing Reporter ```rust= fn error_chain_fmt( e: &impl std::error::Error, f: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { writeln!(f, "{}\n", e)?; let mut current = e.source(); while let Some(cause) = current { writeln!(f, "Caused by:\n\t{}", cause)?; current = cause.source(); } Ok(()) } ``` <!-- .element: class="fragment" --> Note: The Error trait needs something to iterate over sources and backtraces to print a full error report ---- The ecosystem currently abuses `Debug` ```rust= impl std::fmt::Debug for StoreTokenError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { error_chain_fmt(self, f) } } ``` <!-- .element: class="fragment" --> ---- We should provide reasonable defaults std::error::Report - Single line <!-- .element: class="fragment" data-fragment-index="1" --> ```rust= println!("Error: {}", Report::from(error)); // Outputs: // Error: outermost error: second error: root error ``` <!-- .element: class="fragment" data-fragment-index="1" --> Note: std should provide a reasonable default Reporter ---- std::error::Report - Multi line ```rust= println!("Error: {:#}", Report::from(error)) // Outputs: // Error: outermost error // // Caused by: // 0: second error // 1: root error ``` ---- Convenience method on Error trait ```rust= fn report(&self) -> impl Display + '_ where Self: Sized, { Report::from(self) } // ... println!("Error: {}", error.report()); ``` --- Stabilizing existing work progress * <!-- .element: class="fragment" --> Backtrace * <!-- .element: class="fragment" --> Error trait * <!-- .element: class="fragment" --> Termination trait Note: Error trait needs to be compatible with core, main issue is Backtrace Termination trait also needs specialization to use Error instead of Debug when appropriate, --- Mitigating problems with `Box<dyn Error>` ```diff= - impl<T: Error> Error for Box<T> { + impl<T: Error + ?Sized> Error for Box<T> { ``` <!-- .element: class="fragment" --> * <!-- .element: class="fragment" --> Doesn't implement the Error trait * <!-- .element: class="fragment" --> Can't benefit from specialization fixes to Termination/unwrap/expect Note: Can fix the original issue by properly leveraging the new `Try` trait Can't apply this change to existing type, would need to deprecate and replace `Box<dyn Error>` Can specialize the relevant API's directly --- Future Work: * <!-- .element: class="fragment" --> Error Handling Book * <!-- .element: class="fragment" --> Ergonomic error handling changes * <!-- .element: class="fragment" --> Support accessing any context in an error, not just `source` and `backtrace` * <!-- .element: class="fragment" --> Error return traces * <!-- .element: class="fragment" --> Better support panics that unconditionally abort * <!-- .element: class="fragment" --> And more... Note: leaning towards wanting a custom derive, lots of challenges here though will probably just rely on error trait and `panic_error`
{"metaMigratedAt":"2023-06-16T00:21:39.268Z","metaMigratedFrom":"YAML","title":"2: Error Handling PG Update","breaks":true,"contributors":"[{\"id\":\"d9a7ad08-01c7-4b9c-8fac-340882a1a8d9\",\"add\":7998,\"del\":3681},{\"id\":\"27d8f2ac-a5dc-4ebe-8c31-cc45bcd8447e\",\"add\":96,\"del\":118}]"}
    315 views
   Owned this note