about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs4
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs3
-rw-r--r--compiler/rustc_middle/src/ty/util.rs36
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs8
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs7
-rw-r--r--compiler/rustc_passes/src/check_attr.rs25
-rw-r--r--compiler/rustc_passes/src/dead.rs20
-rw-r--r--compiler/rustc_passes/src/reachable.rs28
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs39
-rw-r--r--compiler/rustc_typeck/src/collect.rs31
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 72c38d41d5b..433ef978b64 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 54eb2dc9e28..321fcd43797 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 03d3a4a8c5f..f0710ef42de 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 1c8af13ce9c..646d4c9f8f5 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<DefId> {
         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 a841cce23de..b90eecefc0c 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<Symbol>,
+    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<LocalD
             BodyUnsafety::Safe
         }
     });
-    let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
+    let body_target_features: &[_] = if tcx.has_codegen_attrs(tcx.def_kind(def.did)) {
+        &tcx.codegen_fn_attrs(def.did).target_features
+    } else {
+        &[]
+    };
     let safety_context =
         if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
     let mut visitor = UnsafetyVisitor {
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index dde79214b16..3f567633e4a 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -375,7 +375,12 @@ impl<'tcx> 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 b297012f19f..72cbdbcf8cf 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 991d0d45546..f0451352b45 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 b603352a9be..e9f4bfee3de 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 0ff0267d0ce..2936b6775d1 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 bf62a8e84d7..7be5d7b8e97 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<Symbol> {
+fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
     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)
 }