#![feature(try_trait_v2, try_trait_v2_residual)] // rustc_ast_lowering/src/expr.rs:1945-2033 @8d1a764. use std::ops::ControlFlow; use std::task::Poll; fn flow(x: ControlFlow) -> ControlFlow { let v = x?; ControlFlow::Continue(v + 1) } fn option(x: Option) -> Option { Some(x? + 1) } fn result(x: Result) -> Result { Ok(x? + 1) } #[test] fn try_carriers() { assert!(matches!(flow(ControlFlow::Continue(2)), ControlFlow::Continue(3))); assert!(matches!(flow(ControlFlow::Break(4)), ControlFlow::Break(4))); assert_eq!(option(Some(2)), Some(3)); assert_eq!(option(None), None); assert_eq!(result(Ok(2)), Ok(3)); assert_eq!(result(Err(4)), Err(4)); } fn poll_result(x: Poll>) -> Poll> { match x? { Poll::Ready(v) => Poll::Ready(Ok(v + 1)), Poll::Pending => Poll::Pending } } fn poll_option(x: Poll>>) -> Poll>> { match x? { Poll::Ready(Some(v)) => Poll::Ready(Some(Ok(v + 1))), Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending } } #[test] fn try_poll_branches() { assert_eq!(poll_result(Poll::Ready(Ok(2))), Poll::Ready(Ok(3))); assert_eq!(poll_result(Poll::Ready(Err(4))), Poll::Ready(Err(4))); assert_eq!(poll_result(Poll::Pending), Poll::Pending); assert_eq!(poll_option(Poll::Ready(Some(Ok(2)))), Poll::Ready(Some(Ok(3)))); assert_eq!(poll_option(Poll::Ready(Some(Err(4)))), Poll::Ready(Some(Err(4)))); assert_eq!(poll_option(Poll::Ready(None)), Poll::Ready(None)); assert_eq!(poll_option(Poll::Pending), Poll::Pending); } enum Carrier { Value(T), Stop } impl std::ops::Residual for Carrier { type TryType = Carrier; } impl std::ops::Try for Carrier { type Output = T; type Residual = Carrier; fn from_output(value: T) -> Self { Self::Value(value) } fn branch(self) -> ControlFlow { match self { Self::Value(value) => ControlFlow::Continue(value), Self::Stop => ControlFlow::Break(Carrier::Stop) } } } impl std::ops::FromResidual> for Carrier { fn from_residual(residual: Carrier) -> Self { match residual { Carrier::Stop => Self::Stop, Carrier::Value(never) => match never {} } } } fn carrier(value: Carrier) -> Carrier { Carrier::Value(value? + 1) } #[test] fn user_defined_try_carrier() { assert!(matches!(carrier(Carrier::Value(3)), Carrier::Value(4))); assert!(matches!(carrier(Carrier::Stop), Carrier::Stop)); }