Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit unused_attributes for #[inline] on exported functions #138842

Merged
merged 1 commit into from
Mar 31, 2025
Merged
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
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ impl CodegenFnAttrs {
/// * `#[no_mangle]` is present
/// * `#[export_name(...)]` is present
/// * `#[linkage]` is present
///
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
pub fn contains_extern_indicator(&self) -> bool {
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|| self.export_name.is_some()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ impl<'tcx> MonoItem<'tcx> {

// If the function is #[naked] or contains any other attribute that requires exactly-once
// instantiation:
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ passes_inline_ignored_constants =
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "65833")}

passes_inline_ignored_for_exported =
`#[inline]` is ignored on externally exported functions
.help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`

passes_inline_ignored_function_prototype =
`#[inline]` is ignored on function prototypes

Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
});
}
}

// `#[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))
{
let attrs = self.tcx.codegen_fn_attrs(did);
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
if attrs.contains_extern_indicator() {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::InlineIgnoredForExported {},
);
}
}
}

/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,11 @@ pub(crate) struct OnlyHasEffectOn {
pub target_name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_inline_ignored_for_exported)]
#[help]
pub(crate) struct InlineIgnoredForExported {}

#[derive(Diagnostic)]
#[diag(passes_object_lifetime_err)]
pub(crate) struct ObjectLifetimeErr {
Expand Down
30 changes: 30 additions & 0 deletions tests/ui/lint/inline-exported.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`,
//! because `#[inline]` is ignored for such functions.

#![crate_type = "lib"]

#![feature(linkage)]
#![feature(naked_functions)]
#![deny(unused_attributes)]

#[inline]
//~^ ERROR: `#[inline]` is ignored on externally exported functions
#[no_mangle]
fn no_mangle() {}

#[inline]
//~^ ERROR: `#[inline]` is ignored on externally exported functions
#[export_name = "export_name"]
fn export_name() {}

#[inline]
//~^ ERROR: `#[inline]` is ignored on externally exported functions
#[linkage = "external"]
fn external_linkage() {}

#[inline]
fn normal() {}

#[inline]
#[linkage = "internal"] // not exported
fn internal_linkage() {}
31 changes: 31 additions & 0 deletions tests/ui/lint/inline-exported.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
error: `#[inline]` is ignored on externally exported functions
--> $DIR/inline-exported.rs:10:1
|
LL | #[inline]
| ^^^^^^^^^
|
= help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
note: the lint level is defined here
--> $DIR/inline-exported.rs:8:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^

error: `#[inline]` is ignored on externally exported functions
--> $DIR/inline-exported.rs:15:1
|
LL | #[inline]
| ^^^^^^^^^
|
= help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`

error: `#[inline]` is ignored on externally exported functions
--> $DIR/inline-exported.rs:20:1
|
LL | #[inline]
| ^^^^^^^^^
|
= help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`

error: aborting due to 3 previous errors

12 changes: 6 additions & 6 deletions tests/ui/target-feature/invalid-attribute.stderr
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no idea what happened here

Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ LL |
LL | trait Baz {}
| ------------ not a function definition

error: cannot use `#[inline(always)]` with `#[target_feature]`
--> $DIR/invalid-attribute.rs:69:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:74:1
|
Expand Down Expand Up @@ -163,12 +169,6 @@ error: malformed `target_feature` attribute input
LL | #[target_feature(disable = "baz")]
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`

error: cannot use `#[inline(always)]` with `#[target_feature]`
--> $DIR/invalid-attribute.rs:69:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^

error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/invalid-attribute.rs:81:1
|
Expand Down
Loading