So @Amanieu has a PR that seems quite relevant to this working group =) I'm behind on our Zulip channels right now but I wanted to make sure we discussed it. At least based on the "main description" it sounds pretty great!
This PR allows C++ exceptions (and any other exceptions) to safely unwind through Rust code. In particular:
- Drop code will be executed as the exception unwinds through the stack, as with a Rust panic.
catch_unwindwill not catch the exception, instead the exception will silently continue unwinding past it.
Incidentally, Rust panics can unwind just fine through C++ code as long as you mark the function with
#[unwind(allowed)]. I've added a test for it to be sure.
I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined.
Yes, Centril tagged me! I'll check it out. I meant to read the two RFC drafts yesterday but did not finish yet, unfortunately.
Oh I didn't realize there was a WG for this. I only looked into this because @gnzlbg mentioned it to me.
@Amanieu Welcome! We plan to announce our existence...soon...ish.
I'm done with the PR. I've updated the description with details of the new behavior, so you can use it as a base for what to allow/disallow in this WG.
I think that there is quorum that allowing foreign exceptions to unwind through Rust code at some point would be ok
The main controversy is whether one should be able to catch them or not from Rust @Amanieu
That is, whether it should be possible to catch them at all, and if so, whether
catch_unwind or something else
The main issue is that the signature of
catch_unwind really isn't suited for returning a caught foreign exception.
There is also the implementation issue of how should
catch_unwind (or similar) deal with forced exceptions, etc.
but yes, the signature is a big problem
Or longjmp exceptions on Windows.
those aren't technically forced, but handling longjmp on windows differently would mean that longjmp behaves differently across platforms
and a lot of code might want to rely on that not happening, but the truth is that
longjmp does behave very differently across platforms
It already behaves differently across platforms: it only runs destructors on MSVC, not on MinGW or any non-Windows platform.
My current opinion is that
catch_unwind should ignore foreign exceptions always
and If we want to add support for catching foreign exceptions, that should be a different API
IMO we should just do the same as C++ and say longjmp is UB if it unwinds through frames with destructors.
Yes I agree.
the thing is that while C++ as a language says its UB, the implementations of C++ sometimes say "that is actually guaranteed to do X" (MSVC documents that longjmp runs destructors, and that's a guarantee there, so code for that platform can rely on that)
Actually MSVC documents that longjmp sometimes runs desctructors, depending on compiler options. And it has a big warning box saying that relying on this is nonportable.
It also depends on
MSVC documents that destructors of
noexcept functions might or might not be run depending on the function being inlined
but there is a long shot from that to "UB"
I prefer to provide reasonables guarantees for the two types of unwinding that we have in general, the one that runs destructors, and the one that does not
and then what longjmp does on platform X depends on how platform X implements longjmp
but the language doesn't have to say anything about that
(we want to probably document what each platform does)