From fbe0075a86601e490ae217f3b291768759c39930 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 27 Feb 2025 09:22:19 +0800 Subject: [PATCH] Don't infer unwinding of virtual calls based on the function attributes --- compiler/rustc_ty_utils/src/abi.rs | 19 +++++++++++++------ .../virtual-call-attrs-issue-137646.rs | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 4fa8c9fe15d..74ab65b4f58 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -543,11 +543,13 @@ fn fn_abi_new_uncached<'tcx>( instance: Option>, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let tcx = cx.tcx(); - let (caller_location, fn_def_id, is_virtual_call) = if let Some(instance) = instance { + let (caller_location, determined_fn_def_id, is_virtual_call) = if let Some(instance) = instance + { + let is_virtual_call = matches!(instance.def, ty::InstanceKind::Virtual(..)); ( instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()), - Some(instance.def_id()), - matches!(instance.def, ty::InstanceKind::Virtual(..)), + if is_virtual_call { None } else { Some(instance.def_id()) }, + is_virtual_call, ) } else { (None, None, false) @@ -577,7 +579,7 @@ fn fn_abi_new_uncached<'tcx>( }; let is_drop_in_place = - fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace)); + determined_fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace)); let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, &'tcx FnAbiError<'tcx>> { let span = tracing::debug_span!("arg_of"); @@ -633,7 +635,12 @@ fn fn_abi_new_uncached<'tcx>( c_variadic: sig.c_variadic, fixed_count: inputs.len() as u32, conv, - can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi), + can_unwind: fn_can_unwind( + tcx, + // Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call. + determined_fn_def_id, + sig.abi, + ), }; fn_abi_adjust_for_abi( cx, @@ -642,7 +649,7 @@ fn fn_abi_new_uncached<'tcx>( // If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other // functions from vtable. Internally, `deduced_param_attrs` attempts to infer attributes by // visit the function body. - fn_def_id.filter(|_| !is_virtual_call), + determined_fn_def_id, ); debug!("fn_abi_new_uncached = {:?}", fn_abi); fn_abi_sanity_check(cx, &fn_abi, sig.abi); diff --git a/tests/codegen/virtual-call-attrs-issue-137646.rs b/tests/codegen/virtual-call-attrs-issue-137646.rs index 72a25b75856..5e453947f27 100644 --- a/tests/codegen/virtual-call-attrs-issue-137646.rs +++ b/tests/codegen/virtual-call-attrs-issue-137646.rs @@ -4,8 +4,10 @@ //@ compile-flags: -C opt-level=3 -C no-prepopulate-passes #![crate_type = "lib"] +#![feature(rustc_attrs)] pub trait Trait { + #[rustc_nounwind] fn m(&self, _: (i32, i32, i32)) {} } @@ -16,3 +18,20 @@ pub fn foo(trait_: &dyn Trait) { // CHECK-NOT: readonly trait_.m((1, 1, 1)); } + +#[no_mangle] +#[rustc_nounwind] +pub fn foo_nounwind(trait_: &dyn Trait) { + // CHECK-LABEL: @foo_nounwind( + // FIXME: Here should be invoke. + // COM: CHECK: invoke + trait_.m((1, 1, 1)); +} + +#[no_mangle] +pub extern "C" fn c_nounwind(trait_: &dyn Trait) { + // CHECK-LABEL: @c_nounwind( + // FIXME: Here should be invoke. + // COM: CHECK: invoke + trait_.m((1, 1, 1)); +}