Thanks for the ping! Yeah in the Async WG we've got a pretty good idea of how we can make async Drop
a reality. And it's a pretty good question: if we can make a version of Drop
work which has an async
effect, perhaps we could also make a version of Drop
work which carries a try
effect. I haven't fully explored the design space yet, so I can't say for sure - but at the very least I think it's that might hold promise, and is worth exploring.
One interesting problem which any design will need to grapple with: What should happen if you're returning an error from a function, and one of the destructors also returns an error?
fn example() -> io::Result<()> {
let mut file = File::open("example.md")?; // 1. Pretend `File` implements fallible drop
do_something()?; // 2. This may return an error.
// 3. `File` is dropped here and may return an error
}
The issue here is that when 2.
returns an error, File
will be dropped in 3.
which may also return an error. If both happen at the same time, then we now have instances of io::Error
we may want to return. But the signature as written only supports returning a single error.
I think this requires us to either start discarding errors (which I think defeats the point of this), or introducing some form of standard "aggregate error" in the return type which would enable us to return multiple errors. If we then also consider the existence of Error::source
which supports "error chaining", I think we're effectively looking at some sort of "error tree"?