Extend Result with accept_err(Error::Variant)

I sometimes find myself wanting to panic on error unless a specific variant occurred. A good example might be creating a new directory. I could check if the directory exists and create it only if it does not. However this could (in theory) go wrong if its created in between. So I usually just create the directory and catch the AlreadyExists case. This ends up looking like this:

    match fs::create_dir("path/should/exist") {
        Ok(_) => (),
        Err(e) if e.kind() == ErrorKind::AlreadyExists => (),
        Err(e) => panic!("could not create directory: {e:?}"),
    }

I could extend Result (via a trait) to handle this in an unwrap like function. It would only work on cases where nothing needs to be returned. It could look something like this:

fs::create_dir("path/should/exist").accept_err(ErrorKind::AlreadyExists);

Would any of you be interested in something like this?

Would I be interested? I mean, it's quite neat, but probably not something I would add a new dependency for.

I played around with it a bit, with std::io::Error you need to match on the errorkind. This makes things a bit less pretty.

pub trait AcceptErr {
    type Error;
    fn accept_fn<P: FnMut(&Self::Error) -> bool>(self, predicate: P) -> Self;
}

impl<E> AcceptErr for Result<(), E> {
    type Error = E;
    fn accept_fn<P: FnMut(&Self::Error) -> bool>(self, mut predicate: P) -> Self {
        match self {
            Ok(_) => Ok(()),
            Err(e) if predicate(&e) => Ok(()),
            Err(e) => Err(e),
        }
    }
}

which is then used as follows:

fs::create_dir("path/should/exist").accept_fn(|e| e.kind == ErrorKind::AlreadyExists);

Not something anyone wants to add a dependency for, the question is does this fit in the standard lib. It might not be worth adding a method that only works Result<(), E>. I do not know how this is decided. Should I draft an RFC?

I wondered about that (in the context of blanket implementations) and came up with this. Feel free to use or modify it for your own means.

You could try a PR, though you might want more of a motivation. Your example ignores trying to create a directory over a file (though it will probably just result in an error later and everything FS-wise is ToCToU-prone anyway).

RFCs are usually for larger things and often have pre-RFC conversation on IRLO. The process is described in the RFC repo.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.