{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreicjqt3xe4ezdoznwz5fottidfb3pgq5u7rdhwvh7hqhkypnigs5xq",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mjljlt4yi7z2"
},
"path": "/t/code-bloat-caused-by-lack-of-nounwind-attr-on-drop-in-place/24173#post_6",
"publishedAt": "2026-04-16T02:32:03.000Z",
"site": "https://internals.rust-lang.org",
"textContent": "I think it's because rustc emits `invoke` in the IR, which implies unwinding. LLVM's pass for adding nounwind uses:\n\n\n /// Helper for NoUnwind inference predicate InstrBreaksAttribute.\n static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes) {\n if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))\n return false;\n if (const auto *CI = dyn_cast<CallInst>(&I)) {\n if (Function *Callee = CI->getCalledFunction()) {\n // I is a may-throw call to a function inside our SCC. This doesn't\n // invalidate our current working assumption that the SCC is no-throw; we\n // just have to scan that other function.\n if (SCCNodes.contains(Callee))\n return false;\n }\n }\n return true;\n }\n\n\nwhich only allows `call` (`CallInst`).\n\nThis check is relevant for recursive functions. I happen to have `Arc` that is a recursive type, so `Arc::drop_slow` calls `drop_in_place` which may call `Arc::drop_slow` again. In this case `rustc` assuming that `drop_slow` may unwind makes it emit unwind-requiring `invoke` instruction when called recursively, which then cements its status as an unwinding function.\n\nI don't know if LLVM checking for `CallInst` is intentional, or was it meant to be `CallBase` (which would include `InstInvoke`)",
"title": "Code bloat caused by lack of nounwind attr on `drop_in_place`"
}