flux_common/
result.rs

1use std::ops::ControlFlow;
2
3use rustc_errors::{Diagnostic, ErrorGuaranteed};
4
5pub trait ErrorEmitter {
6    #[track_caller]
7    fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed;
8}
9
10pub trait ErrorCollector<E> {
11    type Result;
12
13    fn collect(&mut self, err: E);
14
15    fn into_result(self) -> Self::Result;
16}
17
18impl ErrorCollector<ErrorGuaranteed> for Option<ErrorGuaranteed> {
19    type Result = Result<(), ErrorGuaranteed>;
20
21    fn collect(&mut self, err: ErrorGuaranteed) {
22        *self = Some(err).or(*self);
23    }
24
25    fn into_result(self) -> Self::Result {
26        if let Some(err) = self { Err(err) } else { Ok(()) }
27    }
28}
29
30pub trait ResultExt<T, E> {
31    fn into_control_flow(self) -> ControlFlow<E, T>;
32
33    fn collect_err(self, collector: &mut impl ErrorCollector<E>) -> Option<T>;
34
35    #[track_caller]
36    fn emit<'a>(self, emitter: &'a impl ErrorEmitter) -> Result<T, ErrorGuaranteed>
37    where
38        E: Diagnostic<'a>;
39}
40
41impl<T, E> ResultExt<T, E> for Result<T, E> {
42    fn into_control_flow(self) -> ControlFlow<E, T> {
43        match self {
44            Ok(v) => ControlFlow::Continue(v),
45            Err(e) => ControlFlow::Break(e),
46        }
47    }
48
49    fn collect_err(self, collector: &mut impl ErrorCollector<E>) -> Option<T> {
50        match self {
51            Ok(v) => Some(v),
52            Err(err) => {
53                collector.collect(err);
54                None
55            }
56        }
57    }
58
59    #[track_caller]
60    fn emit<'a>(self, emitter: &'a impl ErrorEmitter) -> Result<T, ErrorGuaranteed>
61    where
62        E: Diagnostic<'a>,
63    {
64        match self {
65            Ok(v) => Ok(v),
66            Err(err) => Err(emitter.emit(err)),
67        }
68    }
69}