rust-lang/rust · error
LLVM does not have support for catchret
Error message
LLVM does not have support for catchret
What it means
This panic is raised by `GenericBuilder::catch_ret` (builder.rs:1807-1813) when the LLVM-C call `LLVMBuildCatchRet` returns None. catchret exits a SEH catch funclet and transfers control back to normal code on MSVC targets; a null return means the linked LLVM cannot produce it. The `.expect("LLVM does not have support for catchret")` guard converts the unsupported instruction into an immediate compiler panic because partial funclet IR is invalid.
Source
Thrown at compiler/rustc_codegen_llvm/src/builder.rs:1813
&[self.val_ty(src)],
&[src],
)
}
}
impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
pub(crate) fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) {
unsafe {
llvm::LLVMAddClause(landing_pad, clause);
}
}
pub(crate) fn catch_ret(
&mut self,
funclet: &Funclet<'ll>,
unwind: &'ll BasicBlock,
) -> &'ll Value {
let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
ret.expect("LLVM does not have support for catchret")
}
pub(crate) fn check_call<'b>(
&mut self,
typ: &str,
fn_ty: &'ll Type,
llfn: &'ll Value,
args: &'b [&'ll Value],
) -> Cow<'b, [&'ll Value]> {
assert!(
self.cx.type_kind(fn_ty) == TypeKind::Function,
"builder::{typ} not passed a function, but {fn_ty:?}"
);
let param_tys = self.cx.func_params_types(fn_ty);
let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.cx.val_ty(v)))
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);View on GitHub (pinned to 22057b88b0)
Solutions
- Use the rustc toolchain's bundled LLVM.
- Rebuild LLVM with EH (`-DLLVM_ENABLE_EH=ON`) and the X86 MSVC target.
- Align rustc and LLVM versions (rebuild from source).
- Avoid the MSVC target or compile with `-Cpanic=abort` to skip catchret emission.
Example fix
// before rustc --target x86_64-pc-windows-msvc -Cpanic=unwind // after rustc --target x86_64-pc-windows-msvc -Cpanic=abort # no catchret needed
Defensive patterns
Strategy: validation
Validate before calling
# catchret returns from a catch handler; emitted alongside catchswitch. # Validate that panic=unwind is even meaningful for this LLVM before relying on it. rustc -C panic=unwind --print=cfg 2>/dev/null | grep -q panic=unwind \ || echo 'NOTE: unwind cfg not honoured; SEH catchret may be unlowerable on this LLVM'
Try / catch
out="$(cargo build 2>&1)"; rc=$?
if [ $rc -ne 0 ]; then
case "$out" in
*"LLVM does not have support for catchret"*)
echo "catchret unlowerable; use a WinEH-capable LLVM or avoid catching across FFI" >&2 ;;
*) echo "$out" >&2 ;;
esac
exit $rc
fi Prevention
- Keep SEH-catching code on the MSVC target and the rustup default LLVM.
- Don't ship custom libLLVM.so alongside rustc unless EH is enabled at LLVM build time.
- Lock the toolchain in CI with rust-toolchain.toml.
- If you only need unwinding (not catching), prefer -Cpanic=unwind on a verified toolchain over SEH catch constructs.
When it happens
Trigger: Compiling any SEH catch block whose exit must be lowered to a `catchret` when targeting `*-pc-windows-msvc`, while LLVM returns null from `LLVMBuildCatchRet`. Triggers at builder.rs:1812-1813 inside the codegen of the catch handler's terminator.
Common situations: Custom/system LLVM lacking MSVC EH; rustc-vs-LLVM version skew; cross-compiling to MSVC with a host LLVM that does not implement catchret.
Related errors
- LLVM does not have support for cleanuppad
- LLVM does not have support for cleanupret
- LLVM does not have support for catchpad
- LLVM does not have support for catchswitch
- got a non-UTF8 data-layout from LLVM
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/c587526409015e72.json.
Report an issue: GitHub.