@@ -273,25 +273,50 @@ pub fn from_fn_attrs(
273
273
} else if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: RUSTC_ALLOCATOR_NOUNWIND ) {
274
274
// Special attribute for allocator functions, which can't unwind
275
275
false
276
- } else if let Some ( id) = id {
276
+ } else if let Some ( _) = id {
277
+ // rust-lang/rust#64655, rust-lang/rust#63909: to minimize
278
+ // risk associated with changing cases where nounwind
279
+ // attribute is attached, this code is deliberately mimicking
280
+ // old control flow based on whether `id` is `Some` or `None`.
281
+ //
282
+ // However, in the long term we should either:
283
+ // - fold this into final else (i.e. stop inspecting `id`)
284
+ // - or better still: whole-heartedly adopt Rust PR #63909.
285
+ //
286
+ // see also Rust RFC 2753.
287
+
277
288
let sig = cx. tcx . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , & sig) ;
278
- if cx. tcx . is_foreign_item ( id) {
279
- // Foreign items like `extern "C" { fn foo(); }` are assumed not to
280
- // unwind
281
- false
282
- } else if sig. abi != Abi :: Rust && sig. abi != Abi :: RustCall {
283
- // Any items defined in Rust that *don't* have the `extern` ABI are
284
- // defined to not unwind. We insert shims to abort if an unwind
285
- // happens to enforce this.
286
- false
287
- } else {
288
- // Anything else defined in Rust is assumed that it can possibly
289
- // unwind
289
+ if sig. abi == Abi :: Rust || sig. abi == Abi :: RustCall {
290
+ // Any Rust method (or `extern "Rust" fn` or `extern
291
+ // "rust-call" fn`) is explicitly allowed to unwind
292
+ // (unless it has no-unwind attribute, handled above).
290
293
true
294
+ } else {
295
+ // Anything else is either:
296
+ //
297
+ // 1. A foreign item (like `extern "C" { fn foo(); }`), or
298
+ //
299
+ // 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
300
+ //
301
+ // Foreign items (case 1) are assumed to not unwind; it is
302
+ // UB otherwise. (At least for now; see also
303
+ // rust-lang/rust#63909 and Rust RFC 2753.)
304
+ //
305
+ // Items defined in Rust with non-Rust ABIs (case 2) are
306
+ // defined to not unwind. We insert shims to abort if an
307
+ // unwind happens to enforce this.
308
+ //
309
+ // In either case, we mark item as explicitly nounwind.
310
+ false
291
311
}
292
312
} else {
293
313
// assume this can possibly unwind, avoiding the application of a
294
314
// `nounwind` attribute below.
315
+ //
316
+ // (But: See comments in previous branch. Specifically, it is
317
+ // unclear whether there is real value in the assumption this
318
+ // can unwind. The conservatism here may just be papering over
319
+ // a real problem by making some UB a bit harder to hit.)
295
320
true
296
321
} ) ;
297
322
0 commit comments