Rollup merge of #150072 - Bryntet:parse_no_link, r=JonathanBrouwer

Port #[no_link] to use attribute parser

Adds `#[no_link]` to the attribute parser, as well as adds tests making sure to FCW warn on `field`, `arm`, and `macrodef `
This commit is contained in:
Jacob Pratt
2025-12-16 23:10:12 -05:00
committed by GitHub
12 changed files with 189 additions and 174 deletions
@@ -47,6 +47,7 @@
pub(crate) mod macro_attrs;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod no_link;
pub(crate) mod non_exhaustive;
pub(crate) mod path;
pub(crate) mod pin_v2;
@@ -0,0 +1,14 @@
use super::prelude::*;
pub(crate) struct NoLinkParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoLinkParser {
const PATH: &[Symbol] = &[sym::no_link];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::ExternCrate),
Warn(Target::Field),
Warn(Target::Arm),
Warn(Target::MacroDef),
]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoLink;
}
@@ -50,6 +50,7 @@
};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::no_link::NoLinkParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
use crate::attributes::path::PathParser as PathAttributeParser;
use crate::attributes::pin_v2::PinV2Parser;
@@ -241,6 +242,7 @@ mod late {
Single<WithoutArgs<MayDangleParser>>,
Single<WithoutArgs<NoCoreParser>>,
Single<WithoutArgs<NoImplicitPreludeParser>>,
Single<WithoutArgs<NoLinkParser>>,
Single<WithoutArgs<NoMangleParser>>,
Single<WithoutArgs<NoStdParser>>,
Single<WithoutArgs<NonExhaustiveParser>>,
@@ -803,6 +803,9 @@ pub enum AttributeKind {
/// Represents `#[no_implicit_prelude]`
NoImplicitPrelude(Span),
/// Represents `#[no_link]`
NoLink,
/// Represents `#[no_mangle]`
NoMangle(Span),
@@ -70,6 +70,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
Naked(..) => No,
NoCore(..) => No,
NoImplicitPrelude(..) => No,
NoLink => No,
NoMangle(..) => Yes, // Needed for rustdoc
NoStd(..) => No,
NonExhaustive(..) => Yes, // Needed for rustdoc
-9
View File
@@ -240,11 +240,6 @@ passes_has_incoherent_inherent_impl =
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits
.label = only adts, extern types and traits are supported
passes_ignored_attr_with_macro =
`#[{$sym}]` is ignored on struct fields, match arms and macro defs
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "80564")}
passes_ignored_derived_impls =
`{$name}` has {$trait_list_len ->
[one] a derived impl
@@ -379,10 +374,6 @@ passes_must_not_suspend =
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait
.label = is not a struct, enum, union, or trait
passes_no_link =
attribute should be applied to an `extern crate` item
.label = not an `extern crate` item
passes_no_main_function =
`main` function not found in crate `{$crate_name}`
.here_is_main = here is a function named `main`
+1 -27
View File
@@ -254,6 +254,7 @@ fn check_attributes(
| AttributeKind::LinkSection { .. }
| AttributeKind::MacroUse { .. }
| AttributeKind::MacroEscape( .. )
| AttributeKind::NoLink
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
| AttributeKind::RustcScalableVector { .. }
@@ -303,7 +304,6 @@ fn check_attributes(
self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
}
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
[sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target),
[sym::rustc_no_implicit_autorefs, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
}
@@ -457,15 +457,6 @@ fn check_attributes(
self.check_mix_no_mangle_export(hir_id, attrs);
}
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,
errors::IgnoredAttrWithMacro { sym },
);
}
fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
for EiiImpl { span, inner_span, eii_macro, impl_marked_unsafe, is_default: _ } in impls {
match target {
@@ -1199,23 +1190,6 @@ fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target)
);
}
/// Checks if `#[no_link]` is applied to an `extern crate`.
fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
Target::ExternCrate => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[no_link]` 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(), "no_link");
}
_ => {
self.dcx().emit_err(errors::NoLink { attr_span: attr.span(), span });
}
}
}
/// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
fn check_rustc_legacy_const_generics(
&self,
-15
View File
@@ -80,12 +80,6 @@ pub(crate) struct OuterCrateLevelAttrSuggestion {
#[diag(passes_inner_crate_level_attr)]
pub(crate) struct InnerCrateLevelAttr;
#[derive(LintDiagnostic)]
#[diag(passes_ignored_attr_with_macro)]
pub(crate) struct IgnoredAttrWithMacro<'a> {
pub sym: &'a str,
}
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_fn)]
pub(crate) struct AttrShouldBeAppliedToFn {
@@ -254,15 +248,6 @@ pub(crate) struct Link {
pub span: Option<Span>,
}
#[derive(Diagnostic)]
#[diag(passes_no_link)]
pub(crate) struct NoLink {
#[primary_span]
pub attr_span: Span,
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_rustc_legacy_const_generics_only)]
pub(crate) struct RustcLegacyConstGenericsOnly {