about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhyd-dev <yd-huang@outlook.com>2021-05-22 03:53:00 +0800
committerhyd-dev <yd-huang@outlook.com>2021-05-23 04:24:42 +0800
commitda0abad492bfacd7bf96481c2d043f00312dfd5b (patch)
tree70b3d00025511a7eeecdd3233cd6b228941e32ef
parent7b3e10c751ba79344591763bc205986b425dc445 (diff)
downloadrust-da0abad492bfacd7bf96481c2d043f00312dfd5b.tar.gz
rust-da0abad492bfacd7bf96481c2d043f00312dfd5b.zip
Move the callee "can unwind" check to the right place
-rw-r--r--compiler/rustc_mir/src/interpret/eval_context.rs14
-rw-r--r--compiler/rustc_mir/src/interpret/terminator.rs61
2 files changed, 37 insertions, 38 deletions
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs
index 78d9c7f44f9..0c7e3780646 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_mir/src/interpret/eval_context.rs
@@ -819,19 +819,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             StackPopCleanup::Goto { ret, unwind } => (
                 true,
                 Some(if unwinding {
-                    let def_id = frame.body.source.def_id();
                     match unwind {
-                        StackPopUnwind::Cleanup(unwind)
-                            // `fn_sig()` can't be used on closures, but closures always have
-                            // "rust-call" ABI, which always allows unwinding anyway.
-                            if self.tcx.is_closure(def_id) || self.fn_can_unwind(
-                                self.tcx.codegen_fn_attrs(def_id).flags,
-                                self.tcx.fn_sig(def_id).abi(),
-                            ) =>
-                        {
-                            unwind
-                        }
-                        _ => {
+                        StackPopUnwind::Cleanup(unwind) => unwind,
+                        StackPopUnwind::NotAllowed => {
                             throw_ub_format!("unwind past a frame that does not allow unwinding")
                         }
                     }
diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs
index cd172c87eb1..af5da625cd8 100644
--- a/compiler/rustc_mir/src/interpret/terminator.rs
+++ b/compiler/rustc_mir/src/interpret/terminator.rs
@@ -17,7 +17,7 @@ use super::{
 };
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    pub(super) fn fn_can_unwind(&self, attrs: CodegenFnAttrFlags, abi: Abi) -> bool {
+    fn fn_can_unwind(&self, attrs: CodegenFnAttrFlags, abi: Abi) -> bool {
         layout::fn_can_unwind(
             self.tcx.sess.panic_strategy(),
             attrs,
@@ -247,37 +247,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         };
 
+        let get_abi = |this: &Self, instance_ty: Ty<'tcx>| match instance_ty.kind() {
+            ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(),
+            ty::Closure(..) => Abi::RustCall,
+            ty::Generator(..) => Abi::Rust,
+            _ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty),
+        };
+
         // ABI check
-        let check_abi = |this: &Self, instance_ty: Ty<'tcx>| -> InterpResult<'tcx> {
-            if M::enforce_abi(this) {
-                let callee_abi = match instance_ty.kind() {
-                    ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(),
-                    ty::Closure(..) => Abi::RustCall,
-                    ty::Generator(..) => Abi::Rust,
-                    _ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty),
-                };
-                let normalize_abi = |abi| match abi {
-                    Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic =>
-                    // These are all the same ABI, really.
-                    {
-                        Abi::Rust
-                    }
-                    abi => abi,
-                };
-                if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
-                    throw_ub_format!(
-                        "calling a function with ABI {} using caller ABI {}",
-                        callee_abi.name(),
-                        caller_abi.name()
-                    )
+        let check_abi = |callee_abi: Abi| -> InterpResult<'tcx> {
+            let normalize_abi = |abi| match abi {
+                Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic =>
+                // These are all the same ABI, really.
+                {
+                    Abi::Rust
                 }
+                abi => abi,
+            };
+            if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
+                throw_ub_format!(
+                    "calling a function with ABI {} using caller ABI {}",
+                    callee_abi.name(),
+                    caller_abi.name()
+                )
             }
             Ok(())
         };
 
         match instance.def {
             ty::InstanceDef::Intrinsic(..) => {
-                check_abi(self, instance.ty(*self.tcx, self.param_env))?;
+                if M::enforce_abi(self) {
+                    check_abi(get_abi(self, instance.ty(*self.tcx, self.param_env)))?;
+                }
                 assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
                 M::call_intrinsic(self, instance, args, ret, unwind)
             }
@@ -298,7 +299,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Check against the ABI of the MIR body we are calling (not the ABI of `instance`;
                 // these can differ when `find_mir_or_eval_fn` does something clever like resolve
                 // exported symbol names).
-                check_abi(self, self.tcx.type_of(body.source.def_id()))?;
+                let callee_def_id = body.source.def_id();
+                let callee_abi = get_abi(self, self.tcx.type_of(callee_def_id));
+
+                if M::enforce_abi(self) {
+                    check_abi(callee_abi)?;
+                }
+
+                let callee_can_unwind =
+                    self.fn_can_unwind(self.tcx.codegen_fn_attrs(callee_def_id).flags, callee_abi);
 
                 self.push_stack_frame(
                     instance,
@@ -306,7 +315,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     ret.map(|p| p.0),
                     StackPopCleanup::Goto {
                         ret: ret.map(|p| p.1),
-                        unwind: if can_unwind {
+                        unwind: if can_unwind && callee_can_unwind {
                             StackPopUnwind::Cleanup(unwind)
                         } else {
                             StackPopUnwind::NotAllowed