From bd1d18660b37f31ebc83bb8afd06b5d07df377c2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 27 Apr 2022 10:22:08 +0200 Subject: [PATCH 1/5] store `codegen_fn_attrs` in crate metadata --- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 1 + compiler/rustc_metadata/src/rmeta/mod.rs | 2 + compiler/rustc_middle/src/query/mod.rs | 1 + compiler/rustc_typeck/src/collect.rs | 60 ++++++++----------- 5 files changed, 31 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index c00c6ce2f71dc..9f7ef3981c75b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -129,6 +129,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, type_of => { table } variances_of => { table } fn_sig => { table } + codegen_fn_attrs => { table } impl_trait_ref => { table } const_param_default => { table } thir_abstract_const => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 77d6ce1e766eb..72c38d41d5b4f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1007,6 +1007,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.def_span[def_id] <- tcx.def_span(def_id)); self.encode_attrs(def_id); record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); + record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); if should_encode_visibility(def_kind) { record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id)); } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a0fd9ef4f87d9..356dad4b56be1 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -14,6 +14,7 @@ use rustc_hir::definitions::DefKey; use rustc_hir::lang_items; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_middle::metadata::ModChild; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::mir; use rustc_middle::thir; @@ -329,6 +330,7 @@ define_tables! { type_of: Table)>, variances_of: Table>, fn_sig: Table)>, + codegen_fn_attrs: Table, impl_trait_ref: Table)>, const_param_default: Table>>, optimized_mir: Table)>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 173028cf5c56b..1abf8e9080ca0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1081,6 +1081,7 @@ rustc_queries! { desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { true } + separate_provide_extern } query asm_target_features(def_id: DefId) -> &'tcx FxHashSet { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index c1c63c460664c..4c6a2ebd93b65 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2610,7 +2610,6 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option fn from_target_feature( tcx: TyCtxt<'_>, - id: DefId, attr: &ast::Attribute, supported_target_features: &FxHashMap>, target_features: &mut Vec, @@ -2679,7 +2678,7 @@ fn from_target_feature( Some(name) => bug!("unknown target feature gate {}", name), None => true, }; - if !allowed && id.is_local() { + if !allowed { feature_err( &tcx.sess.parse_sess, feature_gate.unwrap(), @@ -2693,7 +2692,7 @@ fn from_target_feature( } } -fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage { +fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { use rustc_middle::mir::mono::Linkage::*; // Use the names from src/llvm/docs/LangRef.rst here. Most types are only @@ -2716,28 +2715,20 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage { "private" => Private, "weak" => WeakAny, "weak_odr" => WeakODR, - _ => { - let span = tcx.hir().span_if_local(def_id); - if let Some(span) = span { - tcx.sess.span_fatal(span, "invalid linkage specified") - } else { - tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) - } - } + _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"), } } - -fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { - let attrs = tcx.get_attrs(id); - +fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { + let did = did.expect_local(); + let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did)); let mut codegen_fn_attrs = CodegenFnAttrs::new(); - if tcx.should_inherit_track_caller(id) { + if tcx.should_inherit_track_caller(did) { 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(id) == tcx.lang_items().drop_in_place_fn() { + if Some(did.to_def_id()) == tcx.lang_items().drop_in_place_fn() { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; } } @@ -2745,7 +2736,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { // The panic_no_unwind function called by TerminatorKind::Abort will never // unwind. If the panic handler that it invokes unwind then it will simply // call the panic handler again. - if Some(id) == tcx.lang_items().panic_no_unwind() { + if Some(did.to_def_id()) == tcx.lang_items().panic_no_unwind() { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; } @@ -2760,7 +2751,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::rustc_allocator) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR; } else if attr.has_name(sym::ffi_returns_twice) { - if tcx.is_foreign_item(id) { + if tcx.is_foreign_item(did) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE; } else { // `#[ffi_returns_twice]` is only allowed `extern fn`s. @@ -2773,7 +2764,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { .emit(); } } else if attr.has_name(sym::ffi_pure) { - if tcx.is_foreign_item(id) { + if tcx.is_foreign_item(did) { if attrs.iter().any(|a| a.has_name(sym::ffi_const)) { // `#[ffi_const]` functions cannot be `#[ffi_pure]` struct_span_err!( @@ -2797,7 +2788,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { .emit(); } } else if attr.has_name(sym::ffi_const) { - if tcx.is_foreign_item(id) { + if tcx.is_foreign_item(did) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST; } else { // `#[ffi_const]` is only allowed on foreign functions @@ -2857,7 +2848,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { None => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED, } } else if attr.has_name(sym::cmse_nonsecure_entry) { - if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) { + if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) { struct_span_err!( tcx.sess, attr.span, @@ -2874,11 +2865,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.has_name(sym::track_caller) { - if !tcx.is_closure(id) && tcx.fn_sig(id).abi() != abi::Abi::Rust { + if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); } - if tcx.is_closure(id) && !tcx.features().closure_track_caller { + if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller { feature_err( &tcx.sess.parse_sess, sym::closure_track_caller, @@ -2904,7 +2895,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(s); } } else if attr.has_name(sym::target_feature) { - if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal { + if !tcx.is_closure(did.to_def_id()) + && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal + { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on // WebAssembly targets on all functions, including safe @@ -2930,22 +2923,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { attr.span, "`#[target_feature(..)]` can only be applied to `unsafe` functions", ); - err.span_label(tcx.def_span(id), "not an `unsafe` function"); + err.span_label(tcx.def_span(did), "not an `unsafe` function"); err.emit(); - } else if let Some(local_id) = id.as_local() { - check_target_feature_trait_unsafe(tcx, local_id, attr.span); + } else { + check_target_feature_trait_unsafe(tcx, did, attr.span); } } from_target_feature( tcx, - id, attr, supported_target_features, &mut codegen_fn_attrs.target_features, ); } else if attr.has_name(sym::linkage) { if let Some(val) = attr.value_str() { - codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, val.as_str())); + codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, did, val.as_str())); } } else if attr.has_name(sym::link_section) { if let Some(val) = attr.value_str() { @@ -3161,8 +3153,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { }); // #73631: closures inherit `#[target_feature]` annotations - if tcx.features().target_feature_11 && tcx.is_closure(id) { - let owner_id = tcx.parent(id); + if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) { + let owner_id = tcx.parent(did.to_def_id()); codegen_fn_attrs .target_features .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied()) @@ -3187,7 +3179,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { if !codegen_fn_attrs.no_sanitize.is_empty() { if codegen_fn_attrs.inline == InlineAttr::Always { if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { - let hir_id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(did); tcx.struct_span_lint_hir( lint::builtin::INLINE_NO_SANITIZE, hir_id, @@ -3207,7 +3199,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { // strippable by the linker. // // Additionally weak lang items have predetermined symbol names. - if tcx.is_weak_lang_item(id) { + if tcx.is_weak_lang_item(did.to_def_id()) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } if let Some(name) = weak_lang_items::link_name(attrs) { From 501067cb05c7ed51b2142ed1b0eff968b4fe42e0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 27 Apr 2022 10:44:00 +0200 Subject: [PATCH 2/5] 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` --- compiler/rustc_middle/src/ty/layout.rs | 41 ++++++++++--------- .../src/abort_unwinding_calls.rs | 16 ++++---- compiler/rustc_typeck/src/collect.rs | 9 +--- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cd4b23fca3932..61f6dab1b2145 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -6,6 +6,7 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast as ast; use rustc_attr as attr; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; 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 /// might (from a foreign exception or similar). #[inline] -pub fn fn_can_unwind<'tcx>( - tcx: TyCtxt<'tcx>, - codegen_fn_attr_flags: CodegenFnAttrFlags, - abi: SpecAbi, -) -> bool { - // Special attribute for functions which can't unwind. - if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) { - return false; +pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option, abi: SpecAbi) -> bool { + if let Some(did) = fn_def_id { + // Special attribute for functions which can't unwind. + if tcx.codegen_fn_attrs(did).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 @@ -2991,13 +3000,7 @@ fn fn_abi_of_fn_ptr<'tcx>( ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { let (param_env, (sig, extra_args)) = query.into_parts(); - LayoutCx { tcx, param_env }.fn_abi_new_uncached( - sig, - extra_args, - None, - CodegenFnAttrFlags::empty(), - false, - ) + LayoutCx { tcx, param_env }.fn_abi_new_uncached(sig, extra_args, None, None, false) } fn fn_abi_of_instance<'tcx>( @@ -3014,13 +3017,11 @@ fn fn_abi_of_instance<'tcx>( None }; - let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags; - LayoutCx { tcx, param_env }.fn_abi_new_uncached( sig, extra_args, caller_location, - attrs, + Some(instance.def_id()), matches!(instance.def, ty::InstanceDef::Virtual(..)), ) } @@ -3033,7 +3034,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], caller_location: Option>, - codegen_fn_attr_flags: CodegenFnAttrFlags, + fn_def_id: Option, // FIXME(eddyb) replace this with something typed, like an `enum`. force_thin_self_ptr: bool, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { @@ -3205,7 +3206,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { c_variadic: sig.c_variadic, fixed_count: inputs.len(), 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)?; debug!("fn_abi_new_uncached = {:?}", fn_abi); diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 757dc09375584..ade6555f4d2c1 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,6 +1,5 @@ use crate::MirPass; use rustc_hir::def::DefKind; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::*; use rustc_middle::ty::layout; 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 // unwinding or not. - let body_flags = tcx.codegen_fn_attrs(def_id).flags; let body_ty = tcx.type_of(def_id); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), @@ -54,7 +52,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { ty::Generator(..) => Abi::Rust, _ => 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 // 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, .. } => { let ty = func.ty(body, tcx); let sig = ty.fn_sig(tcx); - let flags = match ty.kind() { - ty::FnPtr(_) => CodegenFnAttrFlags::empty(), - ty::FnDef(def_id, _) => tcx.codegen_fn_attrs(*def_id).flags, + let fn_def_id = match ty.kind() { + ty::FnPtr(_) => None, + &ty::FnDef(def_id, _) => Some(def_id), _ => 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 { .. } => { 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 { .. } => { - layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust) + layout::fn_can_unwind(tcx, None, Abi::Rust) } _ => continue, }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 4c6a2ebd93b65..b2aaaaa235c25 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -45,7 +45,7 @@ use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; 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 std::iter; @@ -2726,13 +2726,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { 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 // unwind. If the panic handler that it invokes unwind then it will simply // call the panic handler again. From 66ff6c32e591c8084dcb63164446587c715d3e47 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 27 Apr 2022 14:50:50 +0200 Subject: [PATCH 3/5] only cache `codegen_fn_attrs` on disk if its local --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1abf8e9080ca0..629a550b77596 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1080,7 +1080,7 @@ rustc_queries! { query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs { desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } storage(ArenaCacheSelector<'tcx>) - cache_on_disk_if { true } + cache_on_disk_if { def_id.is_local() } separate_provide_extern } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index b2aaaaa235c25..bf62a8e84d7f3 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2718,6 +2718,7 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"), } } + fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { let did = did.expect_local(); let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did)); From d371ebe117419b9815bd8743f981d8fa67a876d8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 4 May 2022 11:18:37 +0200 Subject: [PATCH 4/5] only compute `codegen_fn_attrs` where needed --- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- .../src/middle/codegen_fn_attrs.rs | 4 +- compiler/rustc_middle/src/ty/instance.rs | 3 +- compiler/rustc_middle/src/ty/util.rs | 36 +++++++++++++++++ .../rustc_mir_build/src/check_unsafety.rs | 8 +++- .../rustc_mir_transform/src/check_unsafety.rs | 7 +++- compiler/rustc_passes/src/check_attr.rs | 25 +++++++++++- compiler/rustc_passes/src/dead.rs | 20 +++++----- compiler/rustc_passes/src/reachable.rs | 28 +++++++------ compiler/rustc_symbol_mangling/src/lib.rs | 39 ++++++++++++------- compiler/rustc_typeck/src/collect.rs | 31 ++++++++++----- 11 files changed, 154 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 72c38d41d5b4f..433ef978b64a5 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1007,7 +1007,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.def_span[def_id] <- tcx.def_span(def_id)); self.encode_attrs(def_id); record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); - record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); + if tcx.has_codegen_attrs(def_kind) { + record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); + } if should_encode_visibility(def_kind) { record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id)); } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 54eb2dc9e2890..321fcd43797cc 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -95,7 +95,9 @@ bitflags! { } impl CodegenFnAttrs { - pub fn new() -> CodegenFnAttrs { + pub const EMPTY: &'static Self = &Self::new(); + + pub const fn new() -> CodegenFnAttrs { CodegenFnAttrs { flags: CodegenFnAttrFlags::empty(), inline: InlineAttr::None, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 03d3a4a8c5f3c..f0710ef42de3c 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -246,7 +246,8 @@ impl<'tcx> InstanceDef<'tcx> { match *self { InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. }) | InstanceDef::Virtual(def_id, _) => { - tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + tcx.has_codegen_attrs(tcx.def_kind(def_id)) + && tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller, _ => false, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 1c8af13ce9ca1..646d4c9f8f546 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -139,6 +139,42 @@ impl<'tcx> TyCtxt<'tcx> { hasher.finish() } + pub fn has_codegen_attrs(self, def_kind: DefKind) -> bool { + match def_kind { + DefKind::Fn + | DefKind::AssocFn + | DefKind::Ctor(..) + | DefKind::Closure + | DefKind::Generator + | DefKind::Static(_) => true, + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Const + | DefKind::AssocConst + | DefKind::Macro(..) + | DefKind::Use + | DefKind::ForeignMod + | DefKind::OpaqueTy + | DefKind::Impl + | DefKind::Field + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::LifetimeParam + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } + } + pub fn res_generics_def_id(self, res: Res) -> Option { match res { Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index a841cce23dee9..b90eecefc0c52 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -27,7 +27,7 @@ struct UnsafetyVisitor<'a, 'tcx> { body_unsafety: BodyUnsafety, /// The `#[target_feature]` attributes of the body. Used for checking /// calls to functions with `#[target_feature]` (RFC 2396). - body_target_features: &'tcx Vec, + body_target_features: &'tcx [Symbol], /// When inside the LHS of an assignment to a field, this is the type /// of the LHS and the span of the assignment expression. assignment_info: Option<(Ty<'tcx>, Span)>, @@ -661,7 +661,11 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam UnsafetyChecker<'_, 'tcx> { } let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; - let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features; + // Constants don't have codegen attributes, so the body might not have codegen attributes. + let self_features: &[_] = if self.tcx.has_codegen_attrs(self.tcx.def_kind(self.body_did)) { + &self.tcx.codegen_fn_attrs(self.body_did).target_features + } else { + &[] + }; // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b297012f19f2f..72cbdbcf8cff1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -104,6 +104,9 @@ impl CheckAttrVisitor<'_> { sym::rustc_allow_const_fn_unstable => { self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) } + sym::rustc_std_internal_symbol => { + self.check_rustc_std_internal_symbol(&attr, span, target) + } sym::naked => self.check_naked(hir_id, attr, span, target), sym::rustc_legacy_const_generics => { self.check_rustc_legacy_const_generics(&attr, span, target, item) @@ -193,6 +196,7 @@ impl CheckAttrVisitor<'_> { return; } + // FIXME(@lcnr): this doesn't belong here. if matches!(target, Target::Closure | Target::Fn | Target::Method(_) | Target::ForeignFn) { self.tcx.ensure().codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id)); } @@ -1659,7 +1663,7 @@ impl CheckAttrVisitor<'_> { } } sym::align => { - if let (Target::Fn, true) = (target, !self.tcx.features().fn_align) { + if let (Target::Fn, false) = (target, self.tcx.features().fn_align) { feature_err( &self.tcx.sess.parse_sess, sym::fn_align, @@ -1980,6 +1984,25 @@ impl CheckAttrVisitor<'_> { } } + fn check_rustc_std_internal_symbol( + &self, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + match target { + Target::Fn | Target::Static => true, + _ => { + self.tcx + .sess + .struct_span_err(attr.span, "attribute should be applied functions or statics") + .span_label(span, "not a function or static") + .emit(); + false + } + } + } + /// default_method_body_is_const should only be applied to trait methods with default bodies. fn check_default_method_body_is_const( &self, diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 991d0d4554628..f0451352b4503 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -452,15 +452,17 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { } let def_id = tcx.hir().local_def_id(id); - let cg_attrs = tcx.codegen_fn_attrs(def_id); - - // #[used], #[no_mangle], #[export_name], etc also keeps the item alive - // forcefully, e.g., for placing it in a specific section. - if cg_attrs.contains_extern_indicator() - || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) - || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - return true; + if tcx.has_codegen_attrs(tcx.def_kind(def_id)) { + let cg_attrs = tcx.codegen_fn_attrs(def_id); + + // #[used], #[no_mangle], #[export_name], etc also keeps the item alive + // forcefully, e.g., for placing it in a specific section. + if cg_attrs.contains_extern_indicator() + || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) + || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) + { + return true; + } } tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index b603352a9beba..e9f4bfee3deff 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -208,7 +208,11 @@ impl<'tcx> ReachableContext<'tcx> { } else { false }; - let codegen_attrs = self.tcx.codegen_fn_attrs(search_item); + let codegen_attrs = if self.tcx.has_codegen_attrs(self.tcx.def_kind(search_item)) { + self.tcx.codegen_fn_attrs(search_item) + } else { + CodegenFnAttrs::EMPTY + }; let is_extern = codegen_attrs.contains_extern_indicator(); let std_internal = codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); @@ -329,16 +333,18 @@ impl CollectPrivateImplItemsVisitor<'_, '_> { // Anything which has custom linkage gets thrown on the worklist no // matter where it is in the crate, along with "special std symbols" // which are currently akin to allocator symbols. - let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); - if codegen_attrs.contains_extern_indicator() - || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) - // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by - // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their - // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs. - || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED) - || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - self.worklist.push(def_id); + if self.tcx.has_codegen_attrs(self.tcx.def_kind(def_id)) { + let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); + if codegen_attrs.contains_extern_indicator() + || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) + // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by + // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their + // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs. + || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED) + || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) + { + self.worklist.push(def_id); + } } } } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 0ff0267d0ce76..2936b6775d111 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -96,8 +96,10 @@ #[macro_use] extern crate rustc_middle; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::SubstsRef; @@ -175,7 +177,11 @@ fn compute_symbol_name<'tcx>( } // FIXME(eddyb) Precompute a custom symbol name based on attributes. - let attrs = tcx.codegen_fn_attrs(def_id); + let attrs = if tcx.has_codegen_attrs(tcx.def_kind(def_id)) { + tcx.codegen_fn_attrs(def_id) + } else { + CodegenFnAttrs::EMPTY + }; // Foreign items by default use no mangling for their symbol name. There's a // few exceptions to this rule though: @@ -213,20 +219,25 @@ fn compute_symbol_name<'tcx>( return tcx.item_name(def_id).to_string(); } - let avoid_cross_crate_conflicts = - // If this is an instance of a generic function, we also hash in - // the ID of the instantiating crate. This avoids symbol conflicts - // in case the same instances is emitted in two crates of the same - // project. - is_generic(substs) || + // If we're dealing with an instance of a function that's inlined from + // another crate but we're marking it as globally shared to our + // compilation (aka we're not making an internal copy in each of our + // codegen units) then this symbol may become an exported (but hidden + // visibility) symbol. This means that multiple crates may do the same + // and we want to be sure to avoid any symbol conflicts here. + let is_globally_shared_function = matches!( + tcx.def_kind(instance.def_id()), + DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator | DefKind::Ctor(..) + ) && matches!( + MonoItem::Fn(instance).instantiation_mode(tcx), + InstantiationMode::GloballyShared { may_conflict: true } + ); - // If we're dealing with an instance of a function that's inlined from - // another crate but we're marking it as globally shared to our - // compilation (aka we're not making an internal copy in each of our - // codegen units) then this symbol may become an exported (but hidden - // visibility) symbol. This means that multiple crates may do the same - // and we want to be sure to avoid any symbol conflicts here. - matches!(MonoItem::Fn(instance).instantiation_mode(tcx), InstantiationMode::GloballyShared { may_conflict: true }); + // If this is an instance of a generic function, we also hash in + // the ID of the instantiating crate. This avoids symbol conflicts + // in case the same instances is emitted in two crates of the same + // project. + let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function; let instantiating_crate = if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index bf62a8e84d7f3..7be5d7b8e9780 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2720,6 +2720,14 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { } fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { + if cfg!(debug_assertions) { + let def_kind = tcx.def_kind(did); + assert!( + tcx.has_codegen_attrs(def_kind), + "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}", + ); + } + let did = did.expect_local(); let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did)); let mut codegen_fn_attrs = CodegenFnAttrs::new(); @@ -3223,19 +3231,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { /// Computes the set of target features used in a function for the purposes of /// inline assembly. -fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> &'tcx FxHashSet { +fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet { let mut target_features = tcx.sess.target_features.clone(); - let attrs = tcx.codegen_fn_attrs(id); - target_features.extend(&attrs.target_features); - match attrs.instruction_set { - None => {} - Some(InstructionSetAttr::ArmA32) => { - target_features.remove(&sym::thumb_mode); - } - Some(InstructionSetAttr::ArmT32) => { - target_features.insert(sym::thumb_mode); + if tcx.has_codegen_attrs(tcx.def_kind(did)) { + let attrs = tcx.codegen_fn_attrs(did); + target_features.extend(&attrs.target_features); + match attrs.instruction_set { + None => {} + Some(InstructionSetAttr::ArmA32) => { + target_features.remove(&sym::thumb_mode); + } + Some(InstructionSetAttr::ArmT32) => { + target_features.insert(sym::thumb_mode); + } } } + tcx.arena.alloc(target_features) } From 32b13ac9280d15273ef17ee474c0f0a738bb5f5a Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 9 May 2022 17:47:02 +0200 Subject: [PATCH 5/5] review --- compiler/rustc_hir/src/def.rs | 37 +++++++++++++++++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 23 ++++++++++++ compiler/rustc_middle/src/ty/instance.rs | 3 +- compiler/rustc_middle/src/ty/util.rs | 36 ------------------ .../rustc_mir_build/src/check_unsafety.rs | 11 ++---- .../rustc_mir_transform/src/check_unsafety.rs | 8 +--- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 4 +- compiler/rustc_symbol_mangling/src/lib.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 4 +- 11 files changed, 73 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index db8807bad40b1..a639df01a78d4 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -229,6 +229,43 @@ impl DefKind { _ => false, } } + + /// Whether `query get_codegen_attrs` should be used with this definition. + pub fn has_codegen_attrs(self) -> bool { + match self { + DefKind::Fn + | DefKind::AssocFn + | DefKind::Ctor(..) + | DefKind::Closure + | DefKind::Generator + | DefKind::Static(_) => true, + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Const + | DefKind::AssocConst + | DefKind::Macro(..) + | DefKind::Use + | DefKind::ForeignMod + | DefKind::OpaqueTy + | DefKind::Impl + | DefKind::Field + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::LifetimeParam + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } + } } /// The resolution of a path or export. diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 433ef978b64a5..81388a0bf585d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.def_span[def_id] <- tcx.def_span(def_id)); self.encode_attrs(def_id); record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); - if tcx.has_codegen_attrs(def_kind) { + if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } if should_encode_visibility(def_kind) { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4d06c95915b39..9d3d509eb216b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -5,6 +5,7 @@ use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; +use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath}; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar}; @@ -1066,6 +1067,28 @@ pub struct GlobalCtxt<'tcx> { } impl<'tcx> TyCtxt<'tcx> { + /// Expects a body and returns its codegen attributes. + /// + /// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for + /// constants. + pub fn body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs { + let def_kind = self.def_kind(def_id); + if def_kind.has_codegen_attrs() { + self.codegen_fn_attrs(def_id) + } else if matches!( + def_kind, + DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst + ) { + CodegenFnAttrs::EMPTY + } else { + bug!( + "body_codegen_fn_attrs called on unexpected definition: {:?} {:?}", + def_id, + def_kind + ) + } + } + pub fn typeck_opt_const_arg( self, def: ty::WithOptConstParam, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index f0710ef42de3c..7cf7f8973475d 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -246,8 +246,7 @@ impl<'tcx> InstanceDef<'tcx> { match *self { InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. }) | InstanceDef::Virtual(def_id, _) => { - tcx.has_codegen_attrs(tcx.def_kind(def_id)) - && tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller, _ => false, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 646d4c9f8f546..1c8af13ce9ca1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -139,42 +139,6 @@ impl<'tcx> TyCtxt<'tcx> { hasher.finish() } - pub fn has_codegen_attrs(self, def_kind: DefKind) -> bool { - match def_kind { - DefKind::Fn - | DefKind::AssocFn - | DefKind::Ctor(..) - | DefKind::Closure - | DefKind::Generator - | DefKind::Static(_) => true, - DefKind::Mod - | DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::Const - | DefKind::AssocConst - | DefKind::Macro(..) - | DefKind::Use - | DefKind::ForeignMod - | DefKind::OpaqueTy - | DefKind::Impl - | DefKind::Field - | DefKind::TyParam - | DefKind::ConstParam - | DefKind::LifetimeParam - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::GlobalAsm - | DefKind::ExternCrate => false, - } - } - pub fn res_generics_def_id(self, res: Res) -> Option { match res { Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index b90eecefc0c52..6c14f207a7d14 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -643,9 +643,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam body, - Err(_) => return, + let Ok((thir, expr)) = tcx.thir_body(def) else { + return }; let thir = &thir.borrow(); // If `thir` is empty, a type error occurred, skip this body. @@ -661,11 +660,7 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam UnsafetyChecker<'_, 'tcx> { } let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; - // Constants don't have codegen attributes, so the body might not have codegen attributes. - let self_features: &[_] = if self.tcx.has_codegen_attrs(self.tcx.def_kind(self.body_did)) { - &self.tcx.codegen_fn_attrs(self.body_did).target_features - } else { - &[] - }; + // The body might be a constant, so it doesn't have codegen attributes. + let self_features = &self.tcx.body_codegen_attrs(self.body_did.to_def_id()).target_features; // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index f0451352b4503..df28ea4d444ba 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -452,7 +452,7 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { } let def_id = tcx.hir().local_def_id(id); - if tcx.has_codegen_attrs(tcx.def_kind(def_id)) { + if tcx.def_kind(def_id).has_codegen_attrs() { let cg_attrs = tcx.codegen_fn_attrs(def_id); // #[used], #[no_mangle], #[export_name], etc also keeps the item alive diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index e9f4bfee3deff..a5133bfd9459c 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -208,7 +208,7 @@ impl<'tcx> ReachableContext<'tcx> { } else { false }; - let codegen_attrs = if self.tcx.has_codegen_attrs(self.tcx.def_kind(search_item)) { + let codegen_attrs = if self.tcx.def_kind(search_item).has_codegen_attrs() { self.tcx.codegen_fn_attrs(search_item) } else { CodegenFnAttrs::EMPTY @@ -333,7 +333,7 @@ impl CollectPrivateImplItemsVisitor<'_, '_> { // Anything which has custom linkage gets thrown on the worklist no // matter where it is in the crate, along with "special std symbols" // which are currently akin to allocator symbols. - if self.tcx.has_codegen_attrs(self.tcx.def_kind(def_id)) { + if self.tcx.def_kind(def_id).has_codegen_attrs() { let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); if codegen_attrs.contains_extern_indicator() || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 2936b6775d111..ee0994c9ad6cc 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -177,7 +177,7 @@ fn compute_symbol_name<'tcx>( } // FIXME(eddyb) Precompute a custom symbol name based on attributes. - let attrs = if tcx.has_codegen_attrs(tcx.def_kind(def_id)) { + let attrs = if tcx.def_kind(def_id).has_codegen_attrs() { tcx.codegen_fn_attrs(def_id) } else { CodegenFnAttrs::EMPTY diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 7be5d7b8e9780..74714d75fa0ea 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2723,7 +2723,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { if cfg!(debug_assertions) { let def_kind = tcx.def_kind(did); assert!( - tcx.has_codegen_attrs(def_kind), + def_kind.has_codegen_attrs(), "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}", ); } @@ -3233,7 +3233,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { /// inline assembly. fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet { let mut target_features = tcx.sess.target_features.clone(); - if tcx.has_codegen_attrs(tcx.def_kind(did)) { + if tcx.def_kind(did).has_codegen_attrs() { let attrs = tcx.codegen_fn_attrs(did); target_features.extend(&attrs.target_features); match attrs.instruction_set {