Rollup merge of #143138 - JonathanBrouwer:link_name_parser, r=jdonszelmann

Port `#[link_name]` to the new attribute parsing infrastructure

Ports `link_name` to the new attribute parsing infrastructure for https://github.com/rust-lang/rust/issues/131229#issuecomment-2971353197

r? `@jdonszelmann`
This commit is contained in:
Matthias Krüger
2025-06-29 06:59:31 +02:00
committed by GitHub
14 changed files with 96 additions and 70 deletions

View File

@@ -253,6 +253,9 @@ pub enum AttributeKind {
/// Represents `#[inline]` and `#[rustc_force_inline]`.
Inline(InlineAttr, Span),
/// Represents `#[link_name]`.
LinkName { name: Symbol, span: Span },
/// Represents `#[loop_match]`.
LoopMatch(Span),

View File

@@ -29,6 +29,7 @@ impl AttributeKind {
Stability { .. } => Yes,
Cold(..) => No,
ConstContinue(..) => No,
LinkName { .. } => Yes,
LoopMatch(..) => No,
MayDangle(..) => No,
MustUse { .. } => Yes,

View File

@@ -0,0 +1,30 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_attr_data_structures::AttributeKind::LinkName;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
pub(crate) struct LinkNameParser;
impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
const PATH: &[Symbol] = &[sym::link_name];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
cx.expected_name_value(cx.attr_span, None);
return None;
};
let Some(name) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};
Some(LinkName { name, span: cx.attr_span })
}
}

View File

@@ -31,6 +31,7 @@ pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod deprecation;
pub(crate) mod inline;
pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod must_use;

View File

@@ -22,6 +22,7 @@ use crate::attributes::codegen_attrs::{
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::link_attrs::LinkNameParser;
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::must_use::MustUseParser;
@@ -121,6 +122,7 @@ attribute_parsers!(
Single<DeprecationParser>,
Single<ExportNameParser>,
Single<InlineParser>,
Single<LinkNameParser>,
Single<LoopMatchParser>,
Single<MayDangleParser>,
Single<MustUseParser>,

View File

@@ -123,6 +123,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align),
AttributeKind::LinkName { name, .. } => codegen_fn_attrs.link_name = Some(*name),
AttributeKind::NoMangle(attr_span) => {
if tcx.opt_item_name(did.to_def_id()).is_some() {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
@@ -262,7 +263,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
}
}
sym::link_name => codegen_fn_attrs.link_name = attr.value_str(),
sym::link_ordinal => {
link_ordinal_span = Some(attr.span());
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {

View File

@@ -1,4 +1,5 @@
use rustc_abi::FIRST_VARIANT;
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir as hir;
@@ -6,7 +7,7 @@ use rustc_hir::def::DefKind;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, AdtDef, Instance, Ty, TyCtxt};
use rustc_session::declare_lint;
use rustc_span::{Span, Symbol, sym};
use rustc_span::{Span, Symbol};
use tracing::{debug, instrument};
use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub};
@@ -182,7 +183,11 @@ fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: hir::OwnerId) -> SymbolName {
// information, we could have codegen_fn_attrs also give span information back for
// where the attribute was defined. However, until this is found to be a
// bottleneck, this does just fine.
(overridden_link_name, tcx.get_attr(fi, sym::link_name).unwrap().span())
(
overridden_link_name,
find_attr!(tcx.get_all_attrs(fi), AttributeKind::LinkName {span, ..} => *span)
.unwrap(),
)
})
{
SymbolName::Link(overridden_link_name, overridden_link_name_span)

View File

@@ -302,6 +302,7 @@ fn emit_malformed_attribute(
| sym::no_mangle
| sym::must_use
| sym::track_caller
| sym::link_name
) {
return;
}

View File

@@ -191,6 +191,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
}
Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => {
self.check_link_name(hir_id, *attr_span, *name, span, target)
}
Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
self.check_may_dangle(hir_id, *attr_span)
}
@@ -283,7 +286,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target),
[sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
[sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
[sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target),
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
self.check_macro_use(hir_id, attr, target)
@@ -1604,7 +1606,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
fn check_link_name(
&self,
hir_id: HirId,
attr_span: Span,
name: Symbol,
span: Span,
target: Target,
) {
match target {
Target::ForeignFn | Target::ForeignStatic => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@@ -1612,27 +1621,18 @@ 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.span(), "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
// FIXME: #[link_name] was previously allowed on non-functions/statics and some crates
// used this, so only emit a warning.
let attr_span = matches!(target, Target::ForeignMod).then_some(attr.span());
if let Some(s) = attr.value_str() {
let help_span = matches!(target, Target::ForeignMod).then_some(attr_span);
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::LinkName { span, attr_span, value: s.as_str() },
attr_span,
errors::LinkName { span, help_span, value: name.as_str() },
);
} else {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::LinkName { span, attr_span, value: "..." },
);
};
}
}
}

View File

@@ -502,7 +502,7 @@ pub(crate) struct Link {
#[warning]
pub(crate) struct LinkName<'a> {
#[help]
pub attr_span: Option<Span>,
pub help_span: Option<Span>,
#[label]
pub span: Span,
pub value: &'a str,

View File

@@ -17,12 +17,9 @@ extern "C" {
#[link_name]
//~^ ERROR malformed `link_name` attribute input
//~| HELP must be of the form
//~| WARN attribute should be applied to a foreign function or static [unused_attributes]
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
//~| HELP try `#[link(name = "...")]` instead
//~| NOTE expected this to be of the form `link_name = "..."
extern "C" {
fn bar() -> u32;
}
//~^^^ NOTE not a foreign function or static
fn main() {}

View File

@@ -1,8 +1,11 @@
error: malformed `link_name` attribute input
error[E0539]: malformed `link_name` attribute input
--> $DIR/issue-47725.rs:17:1
|
LL | #[link_name]
| ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]`
| ^^^^^^^^^^^^
| |
| expected this to be of the form `link_name = "..."`
| help: must be of the form: `#[link_name = "name"]`
warning: attribute should be applied to a foreign function or static
--> $DIR/issue-47725.rs:3:1
@@ -38,23 +41,6 @@ help: try `#[link(name = "foobar")]` instead
LL | #[link_name = "foobar"]
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: attribute should be applied to a foreign function or static
--> $DIR/issue-47725.rs:17:1
|
LL | #[link_name]
| ^^^^^^^^^^^^
...
LL | / extern "C" {
LL | | fn bar() -> u32;
LL | | }
| |_- not a foreign function or static
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
help: try `#[link(name = "...")]` instead
--> $DIR/issue-47725.rs:17:1
|
LL | #[link_name]
| ^^^^^^^^^^^^
error: aborting due to 1 previous error; 3 warnings emitted
error: aborting due to 1 previous error; 2 warnings emitted
For more information about this error, try `rustc --explain E0539`.

View File

@@ -387,14 +387,6 @@ LL | #![link()]
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
LL | #![link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a function or static
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
|
@@ -411,6 +403,14 @@ LL | #![cold]
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
|
LL | #![link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[must_use]` has no effect when applied to a module
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
|

View File

@@ -89,19 +89,6 @@ note: attribute also specified here
LL | #[automatically_derived]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:86:5
|
LL | #[link_name = "this_does_not_exist"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:88:5
|
LL | #[link_name = "rust_dbg_extern_identity_u32"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:14:1
|
@@ -252,6 +239,19 @@ note: attribute also specified here
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:86:5
|
LL | #[link_name = "this_does_not_exist"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:88:5
|
LL | #[link_name = "rust_dbg_extern_identity_u32"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:92:1
|