Created
February 24, 2021 16:16
-
-
Save dbofmmbt/ef1b476f776e87bdda3a8fab35912172 to your computer and use it in GitHub Desktop.
Revisions
-
dbofmmbt created this gist
Feb 24, 2021 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,107 @@ /// This code was built on @scottmcm 's PR for the new Try trait design. #![feature(try_trait_v2)] #![feature(control_flow_enum)] #![feature(never_type)] #![allow(dead_code)] use std::ops::{ControlFlow, FromResidual, Try}; enum MyFlow<T, S = ()> { Stay(S), Up(T), } struct MyFlowResidual<T>(T); impl<T, S> Try for MyFlow<T, S> { type Ok = S; type Residual = MyFlowResidual<T>; fn from_output(v: <Self as Try>::Ok) -> Self { Self::Stay(v) } fn branch(self) -> ControlFlow<<Self as Try>::Residual, <Self as Try>::Ok> { match self { Self::Stay(it) => ControlFlow::Continue(it), Self::Up(payload) => ControlFlow::Break(MyFlowResidual(payload)), } } } impl<T, S> FromResidual for MyFlow<T, S> { fn from_residual(x: <Self as Try>::Residual) -> Self { MyFlow::Up(x.0.into()) } } impl<T, E> FromResidual<MyFlowResidual<T>> for Result<T, E> { fn from_residual(r: MyFlowResidual<T>) -> Self { Ok(r.0) } } impl<T, E> FromResidual<MyFlow<T, !>> for Result<T, E> { fn from_residual(x: MyFlow<T, !>) -> Self { match x { MyFlow::Up(it) => Ok(it), // I thought that this match would be exaustive without this line below (because of `!` in x), but the compiler complained to me. MyFlow::Stay(_) => panic!(), } } } /// Early Exit for the happy case. trait Lift { type Break; type Continue; fn lift(self) -> MyFlow<Self::Break, Self::Continue>; } impl<T, E> Lift for Result<T, E> { type Break = T; type Continue = E; fn lift(self) -> MyFlow<Self::Break, Self::Continue> { match self { Ok(t) => MyFlow::Up(t), Err(e) => MyFlow::Stay(e), } } } fn main() { println!("Hello, world!"); } fn test() -> Result<usize, String> { a().lift()?; b().lift()?; c().lift()?; Err("end".to_string()) } fn a() -> Result<usize, ()> { Err(()) } fn b() -> Result<usize, ()> { Ok(42) } fn c() -> Result<usize, ()> { Ok(7) } #[cfg(test)] mod tests { use crate::test; #[test] fn it_works() { assert_eq!(test(), Ok(42)); } }