Not sure if this has been mentioned before, but I’ve currently got a lot of code like the following:
fn my_func() -> Result<Obj, MyError> {
let file = File::open("some/path")
.context(ErrorReadingConfig)?
.read_to_end()
.context(ErrorReadingConfig)?;
let mut d = Deserializer::from_bytes(&file);
let val = T::deserialize(&mut d)
.context(ErrorReadingConfig)?;
d.end()
.context(ErrorReadingConfig)?;
Ok(val)
}
Maybe it would be nice to be able to do the following:
fn my_func() -> Result<Obj, MyError> {
try {
let file = File::open("some/path")?
.read_to_end()?;
let mut d = Deserializer::from_bytes(&file);
let val = T::deserialize(&mut d)?;
d.end()?;
val
}.with_context(ErrorReadingConfig)
}
but I don’t know if that’s too much magic.
Was wondering what the current thinking from the powers that be is?
What library is adding in Result::context? It seems like this should be possible to handle via do catch relatively trivially (depending on how that context method works anyway):
fn my_func() -> Result<Obj, MyError> {
let res: Result<Obj, MyError> = do catch {
let file = File::open("some/path")?
.read_to_end()?;
let mut d = Deserializer::from_bytes(&file);
let val = T::deserialize(&mut d)?;
d.end()?;
val
};
res.context(ErrorReadingConfig)
}
The problem is that each error returned is a different type, but each of these different types has a ‘context’ function, which returns the same type for all the input types (basically makes it a trait object and wraps it in a new type with indirection). So this would have to be
let res: Result<Obj, TraitObjectButDontBoxMeYet> ...
This sounds like a job for plain old generics. I’ve encountered a similar situation before, and it’s very easily solvable by extending Result generically and requiring (and implementing) a trait bound on each of the error types. Note that if many types implement a method with the same signature, it should have been a trait anyway. If even the implementation of the .context() method is uniform, then it’s possible that even a default implementation suffices. Something along the lines of:
For the sake of clarity, context here doesn’t take arguments other than self, although the code is easily modified to accommodate additional arguments.