I have an error type that is coming from a template, which might (in fact probably will be) std::io::Error. Then I return a std::io::Error, if the original error is a std::io::Error, I would like to just return it, but if not, I want to wrap it using std::io::Error::new. I can do this using code that looks like:
let error: io::Error = match e.into().downcast::<io::Error>() {
Ok(err) => *err,
Err(err) => io::Error::new(io::ErrorKind::ConnectionAborted, err)
};
where e is constrained to be Into<Box<dyn Error + Send + Sync>>
but, it feels a little wrong to me that I have to Box the error, only to immediately move it out of the box (and free the memory it just allocated).
I can't think of a better way to do this though with current Rust. Although, I think there is a way that it could be done with static dispatch once RFC 1210 lands.
What's the original type of e? How does it achieve being either an io::Error or something else, dynamically? AFAICT that is only possible if it is already a trait object to begin with. And in that case, it must already be behind a pointer (e.g. Box) in order to be passed by-value.
Incidentally, what do you mean by "templating"? Is the I/O error coming from a templating library? Or do you mean "generics", i.e. e is of some type T: Error? (Please do not call generics "templates". Rust generics are not even remotely similar to C++ templates.)
What's the original type of e ? How does it achieve being either an io::Error or something else, dynamically?
The type of e is generic. So the type of e could actually be io::Error, or something else. I'd actually prefer to choose how to handle it statically, but I'm not sure how to do that, hence this topic.
Incidentally, what do you mean by "templating"?
I meant generics. (And incidentally, Rust generics are more similar to C++ templates than, say Go or Java generics, since Rust and C++ both use monomorphization).