convert entire codebase to parsed inline attrs

This commit is contained in:
Jana Dönszelmann
2025-03-07 16:08:13 +01:00
parent 0aade73c50
commit 566f691374
6 changed files with 95 additions and 117 deletions

View File

@@ -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,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::Stability { span, .. }
| AttributeKind::ConstStability { span, .. },
) => self.check_stability_promotable(*span, target),
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 +161,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 +369,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 +433,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 +449,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
attr_span,
errors::IgnoredInlineAttrFnProto,
)
}
@@ -451,25 +460,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 +483,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
attr_span,
errors::InlineIgnoredForExported {},
);
}
@@ -711,6 +717,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[naked]` 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.span(), "naked")
}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
attr_span: attr.span(),
@@ -787,7 +800,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 +843,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 +863,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 +917,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 +1632,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 +1674,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 +1708,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 +1730,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 +1904,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 +1929,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 +2276,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 +2654,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 +2669,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 +2902,8 @@ 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(_, span) => *span) {
tcx.dcx().emit_err(errors::NonExportedMacroInvalidAttrs { attr_span });
}
}
@@ -2908,6 +2923,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,