Skip to content

Commit da0abad

Browse files
author
hyd-dev
committed
Move the callee "can unwind" check to the right place
1 parent 7b3e10c commit da0abad

File tree

2 files changed

+37
-38
lines changed

2 files changed

+37
-38
lines changed

compiler/rustc_mir/src/interpret/eval_context.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -819,19 +819,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
819819
StackPopCleanup::Goto { ret, unwind } => (
820820
true,
821821
Some(if unwinding {
822-
let def_id = frame.body.source.def_id();
823822
match unwind {
824-
StackPopUnwind::Cleanup(unwind)
825-
// `fn_sig()` can't be used on closures, but closures always have
826-
// "rust-call" ABI, which always allows unwinding anyway.
827-
if self.tcx.is_closure(def_id) || self.fn_can_unwind(
828-
self.tcx.codegen_fn_attrs(def_id).flags,
829-
self.tcx.fn_sig(def_id).abi(),
830-
) =>
831-
{
832-
unwind
833-
}
834-
_ => {
823+
StackPopUnwind::Cleanup(unwind) => unwind,
824+
StackPopUnwind::NotAllowed => {
835825
throw_ub_format!("unwind past a frame that does not allow unwinding")
836826
}
837827
}

compiler/rustc_mir/src/interpret/terminator.rs

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use super::{
1717
};
1818

1919
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
20-
pub(super) fn fn_can_unwind(&self, attrs: CodegenFnAttrFlags, abi: Abi) -> bool {
20+
fn fn_can_unwind(&self, attrs: CodegenFnAttrFlags, abi: Abi) -> bool {
2121
layout::fn_can_unwind(
2222
self.tcx.sess.panic_strategy(),
2323
attrs,
@@ -247,37 +247,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
247247
}
248248
};
249249

250+
let get_abi = |this: &Self, instance_ty: Ty<'tcx>| match instance_ty.kind() {
251+
ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(),
252+
ty::Closure(..) => Abi::RustCall,
253+
ty::Generator(..) => Abi::Rust,
254+
_ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty),
255+
};
256+
250257
// ABI check
251-
let check_abi = |this: &Self, instance_ty: Ty<'tcx>| -> InterpResult<'tcx> {
252-
if M::enforce_abi(this) {
253-
let callee_abi = match instance_ty.kind() {
254-
ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(),
255-
ty::Closure(..) => Abi::RustCall,
256-
ty::Generator(..) => Abi::Rust,
257-
_ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty),
258-
};
259-
let normalize_abi = |abi| match abi {
260-
Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic =>
261-
// These are all the same ABI, really.
262-
{
263-
Abi::Rust
264-
}
265-
abi => abi,
266-
};
267-
if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
268-
throw_ub_format!(
269-
"calling a function with ABI {} using caller ABI {}",
270-
callee_abi.name(),
271-
caller_abi.name()
272-
)
258+
let check_abi = |callee_abi: Abi| -> InterpResult<'tcx> {
259+
let normalize_abi = |abi| match abi {
260+
Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic =>
261+
// These are all the same ABI, really.
262+
{
263+
Abi::Rust
273264
}
265+
abi => abi,
266+
};
267+
if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
268+
throw_ub_format!(
269+
"calling a function with ABI {} using caller ABI {}",
270+
callee_abi.name(),
271+
caller_abi.name()
272+
)
274273
}
275274
Ok(())
276275
};
277276

278277
match instance.def {
279278
ty::InstanceDef::Intrinsic(..) => {
280-
check_abi(self, instance.ty(*self.tcx, self.param_env))?;
279+
if M::enforce_abi(self) {
280+
check_abi(get_abi(self, instance.ty(*self.tcx, self.param_env)))?;
281+
}
281282
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
282283
M::call_intrinsic(self, instance, args, ret, unwind)
283284
}
@@ -298,15 +299,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
298299
// Check against the ABI of the MIR body we are calling (not the ABI of `instance`;
299300
// these can differ when `find_mir_or_eval_fn` does something clever like resolve
300301
// exported symbol names).
301-
check_abi(self, self.tcx.type_of(body.source.def_id()))?;
302+
let callee_def_id = body.source.def_id();
303+
let callee_abi = get_abi(self, self.tcx.type_of(callee_def_id));
304+
305+
if M::enforce_abi(self) {
306+
check_abi(callee_abi)?;
307+
}
308+
309+
let callee_can_unwind =
310+
self.fn_can_unwind(self.tcx.codegen_fn_attrs(callee_def_id).flags, callee_abi);
302311

303312
self.push_stack_frame(
304313
instance,
305314
body,
306315
ret.map(|p| p.0),
307316
StackPopCleanup::Goto {
308317
ret: ret.map(|p| p.1),
309-
unwind: if can_unwind {
318+
unwind: if can_unwind && callee_can_unwind {
310319
StackPopUnwind::Cleanup(unwind)
311320
} else {
312321
StackPopUnwind::NotAllowed

0 commit comments

Comments
 (0)