Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser {
.zip(iter::repeat(cx.attr_span))
}

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
check_macro_only(cx, attr_span);
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ impl NoArgsAttributeParser for TrackCallerParser {
const STABILITY: AttributeStability = AttributeStability::Stable;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller;

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
match cx.target {
Target::Fn => {
// `#[track_caller]` is not valid on weak lang items because they are called via
Expand Down Expand Up @@ -571,7 +571,7 @@ impl CombineAttributeParser for TargetFeatureParser {
parse_tf_attribute(cx, args)
}

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
// `#[target_feature]` is incompatible with lang item functions,
// except on WASM where calling target-feature functions is safe (see #84988).
if !cx.sess().target.is_like_wasm && !cx.sess().opts.actually_rustdoc {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl SingleAttributeParser for RustcForceInlineParser {
))
}

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
let Some(inline_span) = find_attr!(cx.parsed_attrs, Inline(attr, span) if !matches!(attr, InlineAttr::Force { .. }) => span)
else {
return;
Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use rustc_abi::ExternAbi;
use rustc_ast::ItemKind;
use rustc_attr_ir::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
use rustc_attr_ir::*;
use rustc_errors::msg;
use rustc_feature::{AttributeStability, Features};
use rustc_lint_defs::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
use rustc_lint_defs::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNUSED_ATTRIBUTES};
use rustc_session::Session;
use rustc_session::diagnostics::feature_err;
use rustc_span::edition::Edition::Edition2024;
Expand All @@ -17,7 +19,7 @@ use crate::attributes::cfg::parse_cfg_entry;
use crate::diagnostics::{
AsNeededCompatibility, BothFfiConstAndPure, BundleNeedsStatic, EmptyLinkName,
ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink,
InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple,
InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, Link, LinkFrameworkApple,
LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection,
RawDylibOnlyWindows, WholeArchiveNeedsStatic,
};
Expand Down Expand Up @@ -258,6 +260,17 @@ impl CombineAttributeParser for LinkParser {
import_name_type,
})
}

fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
let Some(item) = cx.target_item else { return };
let ItemKind::ForeignMod(fm) = &item.kind else { return };
let abi = fm.abi.map_or(ExternAbi::FALLBACK, |abi| {
abi.symbol_unescaped.as_str().parse().unwrap_or(ExternAbi::Rust)
});
if matches!(abi, ExternAbi::Rust) {
cx.emit_lint(UNUSED_ATTRIBUTES, Link, attr_span);
}
}
}

impl LinkParser {
Expand Down Expand Up @@ -584,7 +597,7 @@ impl NoArgsAttributeParser for FfiPureParser {
const STABILITY: AttributeStability = unstable!(ffi_pure);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
// `#[ffi_const]` functions cannot be `#[ffi_pure]`.
if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) {
cx.emit_err(BothFfiConstAndPure { attr_span });
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl NoArgsAttributeParser for RustcPubTransparentParser {
const STABILITY: AttributeStability = unstable!(rustc_attrs);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent;

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
// `#[rustc_pub_transparent]` may only be applied to `#[repr(transparent)]` types.
let is_transparent = find_attr!(
cx.parsed_attrs,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl NoArgsAttributeParser for AllowInternalUnsafeParser {
const STABILITY: AttributeStability = unstable!(allow_internal_unsafe);
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
check_macro_only(cx, attr_span);
}
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub(crate) trait SingleAttributeParser: 'static {
/// combinations. `attr_span` is the span of this attribute.
///
/// Defaults to a no-op.
fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
}

/// Use in combination with [`SingleAttributeParser`].
Expand Down Expand Up @@ -287,7 +287,7 @@ pub(crate) trait NoArgsAttributeParser: 'static {
/// `attr_span` is the span of this attribute.
///
/// Defaults to a no-op.
fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
}

pub(crate) struct WithoutArgs<T: NoArgsAttributeParser>(PhantomData<T>);
Expand All @@ -311,7 +311,7 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> {
Some(T::CREATE(cx.attr_span))
}

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
T::finalize_check(cx, attr_span)
}
}
Expand Down Expand Up @@ -355,7 +355,7 @@ pub(crate) trait CombineAttributeParser: 'static {
/// `attr_span` is the span of the first attribute that was encountered.
///
/// Defaults to a no-op.
fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
}

/// Use in combination with [`CombineAttributeParser`].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl NoArgsAttributeParser for NonExhaustiveParser {
const STABILITY: AttributeStability = AttributeStability::Stable;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
if cx.target != Target::Struct {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> FinalizeOutput;
/// finalized, so it can inspect the fully parsed attributes via
/// [`FinalizeCheckContext::parsed_attrs`]. The [`Span`] is the span of the attribute the
/// check is associated with, used for diagnostics.
pub(crate) type FinalizeCheckFn = fn(&FinalizeCheckContext<'_, '_>, Span);
pub(crate) type FinalizeCheckFn = fn(&mut FinalizeCheckContext<'_, '_>, Span);

/// The result of finalizing a single attribute parser.
pub(crate) struct FinalizeOutput {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,13 @@ pub(crate) struct EmptyLinkName {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("attribute should be applied to an `extern` block with non-Rust ABI")]
#[warning(
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
)]
pub(crate) struct Link;

#[derive(Diagnostic)]
#[diag("link kind `framework` is only supported on Apple targets", code = E0455)]
pub(crate) struct LinkFrameworkApple {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ impl<'sess> AttributeParser<'sess> {
// inspect the fully parsed attributes via `FinalizeCheckContext::parsed_attrs`.
for (check, attr_span) in deferred_checks {
check(
&FinalizeCheckContext {
&mut FinalizeCheckContext {
shared: SharedContext {
cx: self,
target_span,
Expand Down
19 changes: 1 addition & 18 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use std::cell::Cell;
use std::slice;

use rustc_abi::ExternAbi;
use rustc_ast::{AttrStyle, MetaItemKind, ast};
use rustc_attr_parsing::AttributeParser;
use rustc_data_structures::thin_vec::ThinVec;
Expand Down Expand Up @@ -209,7 +208,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
AttributeKind::Naked(..) => self.check_naked(hir_id, target),
AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span),
AttributeKind::Link(_, attr_span) => self.check_link(hir_id, *attr_span, target),
AttributeKind::MacroExport { span, .. } => {
self.check_macro_export(hir_id, *span, target)
}
Expand Down Expand Up @@ -271,6 +269,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::InstructionSet(..) => (),
AttributeKind::InstrumentFn(..) => (),
AttributeKind::Lang(..) => (),
AttributeKind::Link(..) => (),
AttributeKind::LinkName { .. } => (),
AttributeKind::LinkOrdinal { .. } => (),
AttributeKind::LinkSection { .. } => (),
Expand Down Expand Up @@ -1098,22 +1097,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.dcx().emit_err(diagnostics::InvalidMayDangle { attr_span });
}

/// Checks if `#[link]` is applied to an item other than a foreign module.
fn check_link(&self, hir_id: HirId, attr_span: Span, target: Target) {
if target != Target::ForeignMod {
return; // Checked by attribute parser
}

if let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
&& let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
&& !matches!(abi, ExternAbi::Rust)
{
return;
}

self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr_span, diagnostics::Link);
}

/// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
fn check_rustc_legacy_const_generics(
&self,
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,6 @@ pub(crate) struct BothOptimizeNoneAndInline {
pub inline_span: Span,
}

#[derive(Diagnostic)]
#[diag("attribute should be applied to an `extern` block with non-Rust ABI")]
#[warning(
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
)]
pub(crate) struct Link;

#[derive(Diagnostic)]
#[diag("#[rustc_legacy_const_generics] functions must only have const generics")]
pub(crate) struct RustcLegacyConstGenericsOnly {
Expand Down
45 changes: 45 additions & 0 deletions tests/ui/attributes/link-foreign-mod-abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//@ check-pass
//@ compile-flags: --crate-type=lib

#![no_core]
#![feature(no_core, rust_cold_cc, rust_preserve_none_cc, rust_tail_cc, unboxed_closures)]
#![allow(missing_abi)]
#![deny(unfulfilled_lint_expectations, unused_attributes)]

#[link(name = "omitted")]
extern {}

#[link(name = "c")]
extern "C" {}

#[link(name = "rust-call")]
extern "rust-call" {}

#[link(name = "rust-cold")]
extern "rust-cold" {}

#[link(name = "rust-preserve-none")]
extern "rust-preserve-none" {}

#[link(name = "tail")]
extern "tail" {}

#[cfg_attr(any(), link(name = "disabled"))]
extern "Rust" {}

#[expect(unused_attributes)]
#[cfg_attr(all(), link(name = "enabled"))]
extern "Rust" {}

#[allow(unused_attributes)]
#[link(name = "allowed")]
extern "Rust" {}

#[expect(unused_attributes)]
#[link(name = "expected")]
extern "Rust" {}

#[expect(unused_attributes)]
#[link(name = "first")]
#[link(name = "second")]
extern "Rust" {}
13 changes: 13 additions & 0 deletions tests/ui/attributes/link-invalid-abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//@ check-fail
//@ compile-flags: --crate-type=lib

#![no_core]
#![feature(no_core)]
#![warn(unused_attributes)]

#[link(name = "first")]
//~^ WARN
//~| WARN
#[link(name = "second")]
extern "invalid" {}
//~^ ERROR
24 changes: 24 additions & 0 deletions tests/ui/attributes/link-invalid-abi.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0703]: invalid ABI: found `invalid`
--> $DIR/link-invalid-abi.rs:12:8
|
LL | extern "invalid" {}
| ^^^^^^^^^ invalid ABI
|
= note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions

warning: attribute should be applied to an `extern` block with non-Rust ABI
--> $DIR/link-invalid-abi.rs:8:1
|
LL | #[link(name = "first")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
note: the lint level is defined here
--> $DIR/link-invalid-abi.rs:6:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0703`.
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,6 @@ note: the lint level is defined here
LL | #![warn(unused_attributes, unknown_lints)]
| ^^^^^^^^^^^^^^^^^

warning: attribute should be applied to an `extern` block with non-Rust ABI
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
|
LL | #[link(name = "x")] extern "Rust" {}
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

warning: the `macro_use` attribute cannot be used on crates
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:4
|
Expand Down Expand Up @@ -978,6 +970,14 @@ LL | #[link(name = "x")] impl S { }
= help: the `link` attribute can only be applied to foreign modules
= 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 an `extern` block with non-Rust ABI
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
|
LL | #[link(name = "x")] extern "Rust" {}
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

warning: the `must_use` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:3
|
Expand Down
Loading