about summary refs log tree commit diff
path: root/compiler/rustc_passes/src/check_attr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src/check_attr.rs')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs107
1 files changed, 64 insertions, 43 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index dddbf65db72..5ce803aa1f8 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,7 +10,7 @@ use std::collections::hash_map::Entry;
 
 use rustc_abi::{Align, ExternAbi, Size};
 use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast};
-use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
+use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
 use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
@@ -124,6 +124,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     AttributeKind::Stability { span, .. }
                     | AttributeKind::ConstStability { span, .. },
                 ) => self.check_stability_promotable(*span, target),
+                Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
+                Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
+                    self.check_inline(hir_id, *attr_span, span, kind, target)
+                }
                 Attribute::Parsed(AttributeKind::AllowInternalUnstable(syms)) => self
                     .check_allow_internal_unstable(
                         hir_id,
@@ -158,7 +162,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::diagnostic, sym::on_unimplemented, ..] => {
                             self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
                         }
-                        [sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
                         [sym::coverage, ..] => self.check_coverage(attr, span, target),
                         [sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
                         [sym::no_sanitize, ..] => {
@@ -367,11 +370,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         self.check_rustc_force_inline(hir_id, attrs, span, target);
     }
 
-    fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) {
+    fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr_span: Span, sym: &str) {
         self.tcx.emit_node_span_lint(
             UNUSED_ATTRIBUTES,
             hir_id,
-            attr.span(),
+            attr_span,
             errors::IgnoredAttrWithMacro { sym },
         );
     }
@@ -431,7 +434,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     /// Checks if an `#[inline]` is applied to a function or a closure.
-    fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+    fn check_inline(
+        &self,
+        hir_id: HirId,
+        attr_span: Span,
+        defn_span: Span,
+        kind: &InlineAttr,
+        target: Target,
+    ) {
         match target {
             Target::Fn
             | Target::Closure
@@ -440,7 +450,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 self.tcx.emit_node_span_lint(
                     UNUSED_ATTRIBUTES,
                     hir_id,
-                    attr.span(),
+                    attr_span,
                     errors::IgnoredInlineAttrFnProto,
                 )
             }
@@ -451,25 +461,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             Target::AssocConst => self.tcx.emit_node_span_lint(
                 UNUSED_ATTRIBUTES,
                 hir_id,
-                attr.span(),
+                attr_span,
                 errors::IgnoredInlineAttrConstants,
             ),
             // FIXME(#80564): Same for fields, arms, and macro defs
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "inline")
+                self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "inline")
             }
             _ => {
-                self.dcx().emit_err(errors::InlineNotFnOrClosure {
-                    attr_span: attr.span(),
-                    defn_span: span,
-                });
+                self.dcx().emit_err(errors::InlineNotFnOrClosure { attr_span, defn_span });
             }
         }
 
         // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
         if let Some(did) = hir_id.as_owner()
             && self.tcx.def_kind(did).has_codegen_attrs()
-            && !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never))
+            && kind != &InlineAttr::Never
         {
             let attrs = self.tcx.codegen_fn_attrs(did);
             // Not checking naked as `#[inline]` is forbidden for naked functions anyways.
@@ -477,7 +484,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 self.tcx.emit_node_span_lint(
                     UNUSED_ATTRIBUTES,
                     hir_id,
-                    attr.span(),
+                    attr_span,
                     errors::InlineIgnoredForExported {},
                 );
             }
@@ -676,6 +683,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         ) => {
                             continue;
                         }
+                        Attribute::Parsed(AttributeKind::Inline(.., span)) => {
+                            self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
+                                span: *span,
+                                naked_span: attr.span(),
+                                attr: sym::inline.to_string(),
+                            });
+
+                            return;
+                        }
+                        // FIXME(jdonszelmann): make exhaustive
                         _ => {}
                     }
 
@@ -787,7 +804,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
                 for attr in attrs {
-                    self.inline_attr_str_error_with_macro_def(hir_id, attr, "track_caller");
+                    self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "track_caller");
                 }
             }
             _ => {
@@ -830,7 +847,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "non_exhaustive");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "non_exhaustive");
             }
             _ => {
                 self.dcx().emit_err(errors::NonExhaustiveWrongLocation {
@@ -850,7 +867,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "marker");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "marker");
             }
             _ => {
                 self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait {
@@ -904,7 +921,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "target_feature");
             }
             _ => {
                 self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
@@ -1619,7 +1636,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "cold");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "cold");
             }
             _ => {
                 // FIXME: #[cold] was previously allowed on non-functions and some crates used
@@ -1661,7 +1678,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_name");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_name");
             }
             _ => {
                 // FIXME: #[cold] was previously allowed on non-functions/statics and some crates
@@ -1695,7 +1712,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_link");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "no_link");
             }
             _ => {
                 self.dcx().emit_err(errors::NoLink { attr_span: attr.span(), span });
@@ -1717,7 +1734,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "export_name");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "export_name");
             }
             _ => {
                 self.dcx().emit_err(errors::ExportName { attr_span: attr.span(), span });
@@ -1891,7 +1908,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_section");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_section");
             }
             _ => {
                 // FIXME: #[link_section] was previously allowed on non-functions/statics and some
@@ -1916,7 +1933,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle");
+                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "no_mangle");
             }
             // FIXME: #[no_mangle] was previously allowed on non-functions/statics, this should be an error
             // The error should specify that the item that is wrong is specifically a *foreign* fn/static
@@ -2263,9 +2280,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // `#[allow_internal_unstable]` attribute with just a lint, because we previously
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
-            Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable")
-            }
+            Target::Field | Target::Arm | Target::MacroDef => self
+                .inline_attr_str_error_with_macro_def(
+                    hir_id,
+                    attr.span(),
+                    "allow_internal_unstable",
+                ),
             _ => {
                 self.tcx
                     .dcx()
@@ -2638,8 +2658,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         span: Span,
         target: Target,
     ) {
-        let force_inline_attr = attrs.iter().find(|attr| attr.has_name(sym::rustc_force_inline));
-        match (target, force_inline_attr) {
+        match (
+            target,
+            find_attr!(attrs, AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span),
+        ) {
             (Target::Closure, None) => {
                 let is_coro = matches!(
                     self.tcx.hir_expect_expr(hir_id).kind,
@@ -2651,20 +2673,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 );
                 let parent_did = self.tcx.hir_get_parent_item(hir_id).to_def_id();
                 let parent_span = self.tcx.def_span(parent_did);
-                let parent_force_inline_attr =
-                    self.tcx.get_attr(parent_did, sym::rustc_force_inline);
-                if let Some(attr) = parent_force_inline_attr
-                    && is_coro
+
+                if let Some(attr_span) = find_attr!(
+                    self.tcx.get_all_attrs(parent_did),
+                    AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span
+                ) && is_coro
                 {
-                    self.dcx().emit_err(errors::RustcForceInlineCoro {
-                        attr_span: attr.span(),
-                        span: parent_span,
-                    });
+                    self.dcx()
+                        .emit_err(errors::RustcForceInlineCoro { attr_span, span: parent_span });
                 }
             }
             (Target::Fn, _) => (),
-            (_, Some(attr)) => {
-                self.dcx().emit_err(errors::RustcForceInline { attr_span: attr.span(), span });
+            (_, Some(attr_span)) => {
+                self.dcx().emit_err(errors::RustcForceInline { attr_span, span });
             }
             (_, None) => (),
         }
@@ -2885,10 +2906,9 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
 fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
     let attrs = tcx.hir_attrs(item.hir_id());
 
-    for attr in attrs {
-        if attr.has_name(sym::inline) {
-            tcx.dcx().emit_err(errors::NonExportedMacroInvalidAttrs { attr_span: attr.span() });
-        }
+    if let Some(attr_span) = find_attr!(attrs, AttributeKind::Inline(i, span) if !matches!(i, InlineAttr::Force{..}) => *span)
+    {
+        tcx.dcx().emit_err(errors::NonExportedMacroInvalidAttrs { attr_span });
     }
 }
 
@@ -2908,6 +2928,7 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { check_mod_attrs, ..*providers };
 }
 
+// FIXME(jdonszelmann): remove, check during parsing
 fn check_duplicates(
     tcx: TyCtxt<'_>,
     attr: &Attribute,