Skip to content

Instantly share code, notes, and snippets.

@dbofmmbt
Created February 24, 2021 16:16
Show Gist options
  • Save dbofmmbt/ef1b476f776e87bdda3a8fab35912172 to your computer and use it in GitHub Desktop.
Save dbofmmbt/ef1b476f776e87bdda3a8fab35912172 to your computer and use it in GitHub Desktop.
Example of new possibility with the Try trait v2
/// 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));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment