move panic-in-drop=abort check for drop_in_place

Whether `drop_in_place` can abort does depend on the
`panic-in-drop` option while compiling the current crate,
not `core`
This commit is contained in:
lcnr 2022-04-27 10:44:00 +02:00
parent bd1d18660b
commit 501067cb05
3 changed files with 29 additions and 37 deletions

View file

@ -6,6 +6,7 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
@ -2762,14 +2763,22 @@ impl<'tcx> ty::Instance<'tcx> {
/// with `-Cpanic=abort` will look like they can't unwind when in fact they /// with `-Cpanic=abort` will look like they can't unwind when in fact they
/// might (from a foreign exception or similar). /// might (from a foreign exception or similar).
#[inline] #[inline]
pub fn fn_can_unwind<'tcx>( pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
tcx: TyCtxt<'tcx>, if let Some(did) = fn_def_id {
codegen_fn_attr_flags: CodegenFnAttrFlags, // Special attribute for functions which can't unwind.
abi: SpecAbi, if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
) -> bool { return false;
// Special attribute for functions which can't unwind. }
if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
return false; // With -Z panic-in-drop=abort, drop_in_place never unwinds.
//
// This is not part of `codegen_fn_attrs` as it can differ between crates
// and therefore cannot be computed in core.
if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
if Some(did) == tcx.lang_items().drop_in_place_fn() {
return false;
}
}
} }
// Otherwise if this isn't special then unwinding is generally determined by // Otherwise if this isn't special then unwinding is generally determined by
@ -2991,13 +3000,7 @@ fn fn_abi_of_fn_ptr<'tcx>(
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
let (param_env, (sig, extra_args)) = query.into_parts(); let (param_env, (sig, extra_args)) = query.into_parts();
LayoutCx { tcx, param_env }.fn_abi_new_uncached( LayoutCx { tcx, param_env }.fn_abi_new_uncached(sig, extra_args, None, None, false)
sig,
extra_args,
None,
CodegenFnAttrFlags::empty(),
false,
)
} }
fn fn_abi_of_instance<'tcx>( fn fn_abi_of_instance<'tcx>(
@ -3014,13 +3017,11 @@ fn fn_abi_of_instance<'tcx>(
None None
}; };
let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags;
LayoutCx { tcx, param_env }.fn_abi_new_uncached( LayoutCx { tcx, param_env }.fn_abi_new_uncached(
sig, sig,
extra_args, extra_args,
caller_location, caller_location,
attrs, Some(instance.def_id()),
matches!(instance.def, ty::InstanceDef::Virtual(..)), matches!(instance.def, ty::InstanceDef::Virtual(..)),
) )
} }
@ -3033,7 +3034,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
sig: ty::PolyFnSig<'tcx>, sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>], extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>, caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags, fn_def_id: Option<DefId>,
// FIXME(eddyb) replace this with something typed, like an `enum`. // FIXME(eddyb) replace this with something typed, like an `enum`.
force_thin_self_ptr: bool, force_thin_self_ptr: bool,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
@ -3205,7 +3206,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
c_variadic: sig.c_variadic, c_variadic: sig.c_variadic,
fixed_count: inputs.len(), fixed_count: inputs.len(),
conv, conv,
can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi), can_unwind: fn_can_unwind(self.tcx(), fn_def_id, sig.abi),
}; };
self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
debug!("fn_abi_new_uncached = {:?}", fn_abi); debug!("fn_abi_new_uncached = {:?}", fn_abi);

View file

@ -1,6 +1,5 @@
use crate::MirPass; use crate::MirPass;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::layout; use rustc_middle::ty::layout;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
@ -46,7 +45,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
// //
// Here we test for this function itself whether its ABI allows // Here we test for this function itself whether its ABI allows
// unwinding or not. // unwinding or not.
let body_flags = tcx.codegen_fn_attrs(def_id).flags;
let body_ty = tcx.type_of(def_id); let body_ty = tcx.type_of(def_id);
let body_abi = match body_ty.kind() { let body_abi = match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
@ -54,7 +52,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
ty::Generator(..) => Abi::Rust, ty::Generator(..) => Abi::Rust,
_ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
}; };
let body_can_unwind = layout::fn_can_unwind(tcx, body_flags, body_abi); let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi);
// Look in this function body for any basic blocks which are terminated // Look in this function body for any basic blocks which are terminated
// with a function call, and whose function we're calling may unwind. // with a function call, and whose function we're calling may unwind.
@ -73,19 +71,19 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
TerminatorKind::Call { func, .. } => { TerminatorKind::Call { func, .. } => {
let ty = func.ty(body, tcx); let ty = func.ty(body, tcx);
let sig = ty.fn_sig(tcx); let sig = ty.fn_sig(tcx);
let flags = match ty.kind() { let fn_def_id = match ty.kind() {
ty::FnPtr(_) => CodegenFnAttrFlags::empty(), ty::FnPtr(_) => None,
ty::FnDef(def_id, _) => tcx.codegen_fn_attrs(*def_id).flags, &ty::FnDef(def_id, _) => Some(def_id),
_ => span_bug!(span, "invalid callee of type {:?}", ty), _ => span_bug!(span, "invalid callee of type {:?}", ty),
}; };
layout::fn_can_unwind(tcx, flags, sig.abi()) layout::fn_can_unwind(tcx, fn_def_id, sig.abi())
} }
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind
&& layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust) && layout::fn_can_unwind(tcx, None, Abi::Rust)
} }
TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => { TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust) layout::fn_can_unwind(tcx, None, Abi::Rust)
} }
_ => continue, _ => continue,
}; };

View file

@ -45,7 +45,7 @@ use rustc_session::lint;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::{abi, PanicStrategy, SanitizerSet}; use rustc_target::spec::{abi, SanitizerSet};
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
use std::iter; use std::iter;
@ -2726,13 +2726,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
} }
// With -Z panic-in-drop=abort, drop_in_place never unwinds.
if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
if Some(did.to_def_id()) == tcx.lang_items().drop_in_place_fn() {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
}
}
// The panic_no_unwind function called by TerminatorKind::Abort will never // The panic_no_unwind function called by TerminatorKind::Abort will never
// unwind. If the panic handler that it invokes unwind then it will simply // unwind. If the panic handler that it invokes unwind then it will simply
// call the panic handler again. // call the panic handler again.