strum icon indicating copy to clipboard operation
strum copied to clipboard

Feature Request: add `EnumIsAnd` and `EnumIsOr` derive macros

Open amogh-dambal opened this issue 2 months ago • 1 comments

The EnumIs macro is extremely useful, and I think it'd improve ergonomics ever more if strum generated is_*_and and is_*_or methods which allow for chaining conditional comparisons.

One use-case where this is useful is for error enums, especially nested error enums:


#[derive(Debug, thiserror::Error, strum::EnumIs, strum::EnumIsAnd, strum::EnumIsOr)]
enum AppError {
    #[error("i/o error: {0:?}")]
    Io(#[from] std::io::Error),
    #[error("unknown error: {0:?}")]
    Unknown(String),
}

fn foo() -> Result<(), AppError> {
    let f = std::fs::File::create("foo.txt")?;
    f.write_all(b"Hello, world!")?;
    Ok(())
}

fn main() {
    match foo() {
        Ok(_) => {
            info!("success");
        }
        Err(err) => {
            if err.is_io_and(|io_err| match io_err.kind {
                /// Can handle specific I/O errors differently
            ) {
                 /// Do something
        }
   }
}

The idea is to have more ergonomic and readable error handling code when matching on outer error types based on the inner error type.

This functionality can be extensions on the existing EnumIs macro, or entirely separate macros (i.e. EnumIsAnd, EnumIsOr), depending on what makes more sense architecturally.

Happy to work on this and raise a PR, if you think it's useful enough to include in strum and maintain.

amogh-dambal avatar Oct 25 '25 01:10 amogh-dambal

Since let-chains were stabilized in 1.85, I think they're more readable for this purpose than a new method for every variant:

if let AppError::Io(io_err) = err && match io_err.kind /* ... */

vs

if err.is_io_and(|io_err| match io_err.kind

nik-rev avatar Nov 10 '25 15:11 nik-rev