extern “C unwind” notes
  • Target case
  • unwinding over FFI integration
  • Example use cases
  • Rust panics, traverses native frames w/o destructors, panic caught in a Rust frame
  • Main design question at hand
  • extern “C unwind”
  • using “the native” unwinding mechanism, as defined by the target specification
  • DWARF on linux, SEH on msvc
  • extern “C panic”
  • using “the Rust” unwinding mechanism, which may or may not be equal to the target specification
  • any use case for this apart from “it’s easiest”?
  • only one is Rust loading other Rust code, but that’s really more of a case for a stable Rust ABI (or semi-stable)
  • require the Rust unwinding ABI to match the platform
  • it would simplify a lot of things, but has cons
  • maybe it would be worth it to spell out what its pros / cons are 
  • What exactly are we guaranteeing at this point?
  • The reference says:
  • extern "C" -- This is the same as extern fn foo(); whatever the default your C compiler supports.
  • We do not guarantee what happens when a function with an ABI different from "Rust" unwinds anywhere.
  • A useful but minimal guarantee would be that FFI boundaries marked with the new ABI do not explicitly disallow system unwinding to proceed across the boundary; beyond that, it’s all implementation-defined behavior
  • Possible future situations worth considering
  • What if a new unwinding mechanism should arise, where C++ compilers have not yet transitioned, or offer optional support, but we want to adopt it
  • We could change our default target uses, if we think we can get away with it
  • Equivalent to e.g. adopting newer instruction sets
  • This would break any user relying on existent behavior. 
  • Issue a new target that supports this mechanism and people can opt in
  • “rust unwind == native unwind” remains true all the time
  • “rust unwind == native unwind” not true, in which case on older target we require shims
  • What if C++ changes its unwinding mechanism to one that differs from the platform ?
  • Is there a distinction between what C++ uses and the “platform”? eg i686-pc-windows-gnu uses DWARF and i686-pc-windows-msvc uses SEH, despite both being the same architecture and OS
  • Good question. On windows C++ uses synchronous exceptions (SEH) in the MSVC targets, and DWARF or SJLJ on the GNU targets (mingw supports both for C++). For all of them, Windows uses asynchronous exceptions which is slightly different from what C++ uses for MSVC, and very different from what the GNU targets use. I’m not really sure “what’s the platform” in these cases, for C++ code to interoperate, code needs to agree on how C++ exceptions are implemented, and this shows in the target triples, but C++ exceptions are not the platform unwinding mechanism; they are something else built on top, and e.g., other parts of the ABI like RTTI, vtables, etc. also need to match for try /catch to work for C++ code. In Rust the panic payload is a Box<dyn Any + ...> so for the Any to work fat pointer layout, vtables, type_id, etc. all need to match as well.
  • Interactions not addressed in RFC 2753
  • If native code raises an exception, and it traverses Rust stack frames, do destructors run?
  • If native code raises an exception, does catch_panic intercept it?
  • If Rust code raises a panic, and it traverses native frames, what happens?
  • If there are destructors, do they run?
  • Double panics: if native code raises an exception, and it traverses Rust stack frames that panic (e.g. on a destructor), does the program abort ?
  • Key question perhaps
  • Are the points above “undefined behavior” or “implementation defined”?
  • Today, it is definitely UB because of the nounwind attribute and attempts to insert the abort shim
  • Not clear what the real difference is. Perhaps it is that rustc would have to define (and potentially stabilize) that behavior.
  • Perhaps the difference is that we are avoiding LLVM UB — we won’t miscompile the code.
  • Analogy: Rust ABI
  • Idea:
  • spell out the kind of changes that we anticipate and which could happen
  • Key desiderata and/or concerns
  • We shouldn’t constrain our future behavior, for example to adapt to changes in C and C++. 
  • e.g., the proposal to alter our behavior to match new C++ proposals