[Idea] `#[fallible_drop]` attribute for let statements

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"?

5 Likes