Skip to content

Commit c1aa984

Browse files
committed
Emit unused_attributes for #[inline] on exported functions
I saw someone post a code sample that contained these two attributes, which immediately made me suspicious. My suspicions were confirmed when I did a small test and checked the compiler source code to confirm that in these cases, `#[inline]` is indeed ignored (because you can't exactly `LocalCopy`an unmangled symbol since that would lead to duplicate symbols, and doing a mix of an unmangled `GloballyShared` and mangled `LocalCopy` instantiation is too complicated for our current instatiation mode logic, which I don't want to change right now). So instead, emit the usual unused attribute lint with a message saying that the attribute is ignored in this position. I think this is not 100% true, since I expect LLVM `inlinehint` to still be applied to such a function, but that's not why people use this attribute, they use it for the `LocalCopy` instantiation mode, where it doesn't work.
1 parent 81d8edc commit c1aa984

File tree

7 files changed

+89
-0
lines changed

7 files changed

+89
-0
lines changed

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ impl CodegenFnAttrs {
172172
/// * `#[no_mangle]` is present
173173
/// * `#[export_name(...)]` is present
174174
/// * `#[linkage]` is present
175+
///
176+
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
175177
pub fn contains_extern_indicator(&self) -> bool {
176178
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
177179
|| self.export_name.is_some()

compiler/rustc_middle/src/mir/mono.rs

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ impl<'tcx> MonoItem<'tcx> {
117117

118118
// If the function is #[naked] or contains any other attribute that requires exactly-once
119119
// instantiation:
120+
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
120121
let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
121122
if codegen_fn_attrs.contains_extern_indicator()
122123
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)

compiler/rustc_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@ passes_inline_ignored_constants =
383383
.warn = {-passes_previously_accepted}
384384
.note = {-passes_see_issue(issue: "65833")}
385385
386+
passes_inline_ignored_for_exported =
387+
`#[inline]` is ignored on externally exported functions
388+
.help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
389+
386390
passes_inline_ignored_function_prototype =
387391
`#[inline]` is ignored on function prototypes
388392

compiler/rustc_passes/src/check_attr.rs

+16
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
445445
});
446446
}
447447
}
448+
449+
// `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
450+
if let Some(did) = hir_id.as_owner()
451+
&& self.tcx.def_kind(did).has_codegen_attrs()
452+
{
453+
let attrs = self.tcx.codegen_fn_attrs(did);
454+
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
455+
if attrs.contains_extern_indicator() {
456+
self.tcx.emit_node_span_lint(
457+
UNUSED_ATTRIBUTES,
458+
hir_id,
459+
attr.span(),
460+
errors::InlineIgnoredForExported {},
461+
);
462+
}
463+
}
448464
}
449465

450466
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,

compiler/rustc_passes/src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,11 @@ pub(crate) struct OnlyHasEffectOn {
14351435
pub target_name: String,
14361436
}
14371437

1438+
#[derive(LintDiagnostic)]
1439+
#[diag(passes_inline_ignored_for_exported)]
1440+
#[help]
1441+
pub(crate) struct InlineIgnoredForExported {}
1442+
14381443
#[derive(Diagnostic)]
14391444
#[diag(passes_object_lifetime_err)]
14401445
pub(crate) struct ObjectLifetimeErr {

tests/ui/lint/inline-exported.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`,
2+
//! because `#[inline]` is ignored for such functions.
3+
4+
#![crate_type = "lib"]
5+
6+
#![feature(linkage)]
7+
#![feature(naked_functions)]
8+
#![deny(unused_attributes)]
9+
10+
#[inline]
11+
//~^ ERROR: `#[inline]` is ignored on externally exported functions
12+
#[no_mangle]
13+
fn no_mangle() {}
14+
15+
#[inline]
16+
//~^ ERROR: `#[inline]` is ignored on externally exported functions
17+
#[export_name = "export_name"]
18+
fn export_name() {}
19+
20+
#[inline]
21+
//~^ ERROR: `#[inline]` is ignored on externally exported functions
22+
#[linkage = "external"]
23+
fn external_linkage() {}
24+
25+
#[inline]
26+
fn normal() {}
27+
28+
#[inline]
29+
#[linkage = "internal"] // not exported
30+
fn internal_linkage() {}

tests/ui/lint/inline-exported.stderr

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: `#[inline]` is ignored on externally exported functions
2+
--> $DIR/inline-exported.rs:10:1
3+
|
4+
LL | #[inline]
5+
| ^^^^^^^^^
6+
|
7+
= help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
8+
note: the lint level is defined here
9+
--> $DIR/inline-exported.rs:8:9
10+
|
11+
LL | #![deny(unused_attributes)]
12+
| ^^^^^^^^^^^^^^^^^
13+
14+
error: `#[inline]` is ignored on externally exported functions
15+
--> $DIR/inline-exported.rs:15:1
16+
|
17+
LL | #[inline]
18+
| ^^^^^^^^^
19+
|
20+
= help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
21+
22+
error: `#[inline]` is ignored on externally exported functions
23+
--> $DIR/inline-exported.rs:20:1
24+
|
25+
LL | #[inline]
26+
| ^^^^^^^^^
27+
|
28+
= help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
29+
30+
error: aborting due to 3 previous errors
31+

0 commit comments

Comments
 (0)