mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-02 21:17:39 +00:00
83 lines
2.1 KiB
Rust
83 lines
2.1 KiB
Rust
use core::ops::ControlFlow;
|
|
|
|
/// Similar to the `Try` trait, but also implemented for `()`.
|
|
pub trait VisitorResult {
|
|
type Residual;
|
|
fn output() -> Self;
|
|
fn from_residual(residual: Self::Residual) -> Self;
|
|
fn from_branch(b: ControlFlow<Self::Residual>) -> Self;
|
|
fn branch(self) -> ControlFlow<Self::Residual>;
|
|
}
|
|
|
|
impl VisitorResult for () {
|
|
#[cfg(feature = "nightly")]
|
|
type Residual = !;
|
|
|
|
#[cfg(not(feature = "nightly"))]
|
|
type Residual = core::convert::Infallible;
|
|
|
|
fn output() -> Self {}
|
|
fn from_residual(_: Self::Residual) -> Self {}
|
|
fn from_branch(_: ControlFlow<Self::Residual>) -> Self {}
|
|
fn branch(self) -> ControlFlow<Self::Residual> {
|
|
ControlFlow::Continue(())
|
|
}
|
|
}
|
|
|
|
impl<T> VisitorResult for ControlFlow<T> {
|
|
type Residual = T;
|
|
|
|
fn output() -> Self {
|
|
ControlFlow::Continue(())
|
|
}
|
|
fn from_residual(residual: Self::Residual) -> Self {
|
|
ControlFlow::Break(residual)
|
|
}
|
|
fn from_branch(b: Self) -> Self {
|
|
b
|
|
}
|
|
fn branch(self) -> Self {
|
|
self
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! try_visit {
|
|
($e:expr) => {
|
|
match $crate::visit::VisitorResult::branch($e) {
|
|
core::ops::ControlFlow::Continue(()) => (),
|
|
#[allow(unreachable_code)]
|
|
core::ops::ControlFlow::Break(r) => {
|
|
return $crate::visit::VisitorResult::from_residual(r);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! visit_opt {
|
|
($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
|
|
if let Some(x) = $opt {
|
|
$crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! walk_list {
|
|
($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
|
|
for elem in $list {
|
|
$crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! walk_visitable_list {
|
|
($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => {
|
|
for elem in $list {
|
|
$crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?));
|
|
}
|
|
}
|
|
}
|