## 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}]"}