Skip to content

Commit

Permalink
Don't infer unwinding of virtual calls based on the function attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
DianQK committed Feb 27, 2025
1 parent 8089fce commit fbe0075
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
19 changes: 13 additions & 6 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,11 +543,13 @@ fn fn_abi_new_uncached<'tcx>(
instance: Option<ty::Instance<'tcx>>,
) -> 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)
Expand Down Expand Up @@ -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<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
let span = tracing::debug_span!("arg_of");
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions tests/codegen/virtual-call-attrs-issue-137646.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {}
}

Expand All @@ -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));
}

0 comments on commit fbe0075

Please sign in to comment.