pub fn fn_can_unwind<'tcx>(
    tcx: TyCtxt<'tcx>,
    fn_def_id: Option<DefId>,
    abi: SpecAbi
) -> bool
Expand description

Calculates whether a function’s ABI can unwind or not.

This takes two primary parameters:

  • codegen_fn_attr_flags - these are flags calculated as part of the codegen attrs for a defined function. For function pointers this set of flags is the empty set. This is only applicable for Rust-defined functions, and generally isn’t needed except for small optimizations where we try to say a function which otherwise might look like it could unwind doesn’t actually unwind (such as for intrinsics and such).

  • abi - this is the ABI that the function is defined with. This is the primary factor for determining whether a function can unwind or not.

Note that in this case unwinding is not necessarily panicking in Rust. Rust panics are implemented with unwinds on most platform (when -Cpanic=unwind), but this also accounts for -Cpanic=abort build modes. Notably unwinding is disallowed for more non-Rust ABIs unless it’s specifically in the name (e.g. "C-unwind"). Unwinding within each ABI is defined for each ABI individually, but it always corresponds to some form of stack-based unwinding (the exact mechanism of which varies platform-by-platform).

Rust functions are classified whether or not they can unwind based on the active “panic strategy”. In other words Rust functions are considered to unwind in -Cpanic=unwind mode and cannot unwind in -Cpanic=abort mode. Note that Rust supports intermingling panic=abort and panic=unwind code, but only if the final panic mode is panic=abort. In this scenario any code previously compiled assuming that a function can unwind is still correct, it just never happens to actually unwind at runtime.

This function’s answer to whether or not a function can unwind is quite impactful throughout the compiler. This affects things like:

  • Calling a function which can’t unwind means codegen simply ignores any associated unwinding cleanup.
  • Calling a function which can unwind from a function which can’t unwind causes the abort_unwinding_calls MIR pass to insert a landing pad that aborts the process.
  • This affects whether functions have the LLVM nounwind attribute, which affects various optimizations and codegen.

FIXME: this is actually buggy with respect to Rust functions. Rust functions compiled with -Cpanic=unwind and referenced from another crate compiled with -Cpanic=abort will look like they can’t unwind when in fact they might (from a foreign exception or similar).