Skip to content

Commit 4bd3632

Browse files
committed
improve error message when #[naked] is used with #[inline]
1 parent ceec6dd commit 4bd3632

8 files changed

+104
-111
lines changed

compiler/rustc_passes/messages.ftl

+5-6
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,6 @@ passes_break_non_loop =
6969
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
7070
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
7171
72-
passes_cannot_inline_naked_function =
73-
naked functions cannot be inlined
74-
7572
passes_cannot_stabilize_deprecated =
7673
an API can't be stabilized after it is deprecated
7774
.label = invalid version
@@ -485,16 +482,18 @@ passes_naked_functions_asm_block =
485482
passes_naked_functions_asm_options =
486483
asm options unsupported in naked functions: {$unsupported_options}
487484
485+
passes_naked_functions_codegen_attribute =
486+
cannot use additional code generation attributes with `#[naked]`
487+
.label = this attribute is incompatible with `#[naked]`
488+
.label2 = function marked with `#[naked]` here
489+
488490
passes_naked_functions_must_use_noreturn =
489491
asm in naked functions must use `noreturn` option
490492
.suggestion = consider specifying that the asm block is responsible for returning from the function
491493
492494
passes_naked_functions_operands =
493495
only `const` and `sym` operands are supported in naked functions
494496
495-
passes_naked_tracked_caller =
496-
cannot use `#[track_caller]` with `#[naked]`
497-
498497
passes_no_link =
499498
attribute should be applied to an `extern crate` item
500499
.label = not an `extern crate` item

compiler/rustc_passes/src/check_attr.rs

+25-8
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
155155
[sym::rustc_std_internal_symbol] => {
156156
self.check_rustc_std_internal_symbol(attr, span, target)
157157
}
158-
[sym::naked] => self.check_naked(hir_id, attr, span, target),
158+
[sym::naked] => self.check_naked(hir_id, attr, span, target, attrs),
159159
[sym::rustc_never_returns_null_ptr] => {
160160
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
161161
}
@@ -410,12 +410,33 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
410410
}
411411

412412
/// Checks if `#[naked]` is applied to a function definition.
413-
fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
413+
fn check_naked(
414+
&self,
415+
hir_id: HirId,
416+
attr: &Attribute,
417+
span: Span,
418+
target: Target,
419+
attrs: &[Attribute],
420+
) -> bool {
421+
const FORBIDDEN: [rustc_span::Symbol; 3] =
422+
[sym::track_caller, sym::inline, sym::target_feature];
423+
424+
for other_attr in attrs {
425+
if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) {
426+
self.dcx().emit_err(errors::NakedFunctionCodegenAttribute {
427+
span: other_attr.span,
428+
naked_span: attr.span,
429+
});
430+
431+
return false;
432+
}
433+
}
434+
414435
match target {
415436
Target::Fn
416437
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
417438
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
418-
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
439+
// `#[naked]` attribute with just a lint, because we previously
419440
// erroneously allowed it and some crates used it accidentally, to be compatible
420441
// with crates depending on them, we can't throw an error here.
421442
Target::Field | Target::Arm | Target::MacroDef => {
@@ -488,7 +509,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
488509
}
489510
}
490511

491-
/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
512+
/// Checks if a `#[track_caller]` is applied to a function. Returns `true` if valid.
492513
fn check_track_caller(
493514
&self,
494515
hir_id: HirId,
@@ -498,10 +519,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
498519
target: Target,
499520
) -> bool {
500521
match target {
501-
_ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
502-
self.dcx().emit_err(errors::NakedTrackedCaller { attr_span });
503-
false
504-
}
505522
Target::Fn => {
506523
// `#[track_caller]` is not valid on weak lang items because they are called via
507524
// `extern` declarations and `#[track_caller]` would alter their ABI.

compiler/rustc_passes/src/errors.rs

+10-14
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,6 @@ pub struct AttrShouldBeAppliedToFn {
7979
pub on_crate: bool,
8080
}
8181

82-
#[derive(Diagnostic)]
83-
#[diag(passes_naked_tracked_caller, code = E0736)]
84-
pub struct NakedTrackedCaller {
85-
#[primary_span]
86-
pub attr_span: Span,
87-
}
88-
8982
#[derive(Diagnostic)]
9083
#[diag(passes_should_be_applied_to_fn, code = E0739)]
9184
pub struct TrackedCallerWrongLocation {
@@ -1124,13 +1117,6 @@ pub struct UnlabeledCfInWhileCondition<'a> {
11241117
pub cf_type: &'a str,
11251118
}
11261119

1127-
#[derive(Diagnostic)]
1128-
#[diag(passes_cannot_inline_naked_function)]
1129-
pub struct CannotInlineNakedFunction {
1130-
#[primary_span]
1131-
pub span: Span,
1132-
}
1133-
11341120
#[derive(LintDiagnostic)]
11351121
#[diag(passes_undefined_naked_function_abi)]
11361122
pub struct UndefinedNakedFunctionAbi;
@@ -1196,6 +1182,16 @@ pub struct NakedFunctionsMustUseNoreturn {
11961182
pub last_span: Span,
11971183
}
11981184

1185+
#[derive(Diagnostic)]
1186+
#[diag(passes_naked_functions_codegen_attribute, code = E0736)]
1187+
pub struct NakedFunctionCodegenAttribute {
1188+
#[primary_span]
1189+
#[label]
1190+
pub span: Span,
1191+
#[label(passes_label2)]
1192+
pub naked_span: Span,
1193+
}
1194+
11991195
#[derive(Diagnostic)]
12001196
#[diag(passes_attr_only_in_functions)]
12011197
pub struct AttrOnlyInFunctions {

compiler/rustc_passes/src/naked_functions.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ use rustc_span::Span;
1414
use rustc_target::spec::abi::Abi;
1515

1616
use crate::errors::{
17-
CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
18-
NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
19-
UndefinedNakedFunctionAbi,
17+
NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn,
18+
NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi,
2019
};
2120

2221
pub(crate) fn provide(providers: &mut Providers) {
@@ -53,15 +52,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
5352
check_no_patterns(tcx, body.params);
5453
check_no_parameters_use(tcx, body);
5554
check_asm(tcx, def_id, body);
56-
check_inline(tcx, def_id);
57-
}
58-
}
59-
60-
/// Check that the function isn't inlined.
61-
fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
62-
let attrs = tcx.get_attrs(def_id, sym::inline);
63-
for attr in attrs {
64-
tcx.dcx().emit_err(CannotInlineNakedFunction { span: attr.span });
6555
}
6656
}
6757

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ needs-asm-support
2+
#![feature(naked_functions)]
3+
#![crate_type = "lib"]
4+
5+
use std::arch::asm;
6+
7+
#[naked]
8+
pub unsafe extern "C" fn inline_none() {
9+
asm!("", options(noreturn));
10+
}
11+
12+
#[naked]
13+
#[inline]
14+
//~^ ERROR [E0736]
15+
pub unsafe extern "C" fn inline_hint() {
16+
asm!("", options(noreturn));
17+
}
18+
19+
#[naked]
20+
#[inline(always)]
21+
//~^ ERROR [E0736]
22+
pub unsafe extern "C" fn inline_always() {
23+
asm!("", options(noreturn));
24+
}
25+
26+
#[naked]
27+
#[inline(never)]
28+
//~^ ERROR [E0736]
29+
pub unsafe extern "C" fn inline_never() {
30+
asm!("", options(noreturn));
31+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0736]: cannot use additional code generation attributes with `#[naked]`
2+
--> $DIR/naked-functions-inline.rs:13:1
3+
|
4+
LL | #[naked]
5+
| -------- function marked with `#[naked]` here
6+
LL | #[inline]
7+
| ^^^^^^^^^ this attribute is incompatible with `#[naked]`
8+
9+
error[E0736]: cannot use additional code generation attributes with `#[naked]`
10+
--> $DIR/naked-functions-inline.rs:20:1
11+
|
12+
LL | #[naked]
13+
| -------- function marked with `#[naked]` here
14+
LL | #[inline(always)]
15+
| ^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]`
16+
17+
error[E0736]: cannot use additional code generation attributes with `#[naked]`
18+
--> $DIR/naked-functions-inline.rs:27:1
19+
|
20+
LL | #[naked]
21+
| -------- function marked with `#[naked]` here
22+
LL | #[inline(never)]
23+
| ^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]`
24+
25+
error: aborting due to 3 previous errors
26+
27+
For more information about this error, try `rustc --explain E0736`.

tests/ui/asm/naked-functions.rs

-31
Original file line numberDiff line numberDiff line change
@@ -168,37 +168,6 @@ pub unsafe extern "C" fn inline_none() {
168168
}
169169

170170
#[naked]
171-
#[inline]
172-
//~^ ERROR naked functions cannot be inlined
173-
pub unsafe extern "C" fn inline_hint() {
174-
asm!("", options(noreturn));
175-
}
176-
177-
#[naked]
178-
#[inline(always)]
179-
//~^ ERROR naked functions cannot be inlined
180-
pub unsafe extern "C" fn inline_always() {
181-
asm!("", options(noreturn));
182-
}
183-
184-
#[naked]
185-
#[inline(never)]
186-
//~^ ERROR naked functions cannot be inlined
187-
pub unsafe extern "C" fn inline_never() {
188-
asm!("", options(noreturn));
189-
}
190-
191-
#[naked]
192-
#[inline]
193-
//~^ ERROR naked functions cannot be inlined
194-
#[inline(always)]
195-
//~^ ERROR naked functions cannot be inlined
196-
#[inline(never)]
197-
//~^ ERROR naked functions cannot be inlined
198-
pub unsafe extern "C" fn inline_all() {
199-
asm!("", options(noreturn));
200-
}
201-
202171
#[naked]
203172
pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
204173
compile_error!("this is a user specified error")

tests/ui/asm/naked-functions.stderr

+4-40
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ LL | asm!("", options(readonly, nostack), options(pure));
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
66

77
error: this is a user specified error
8-
--> $DIR/naked-functions.rs:204:5
8+
--> $DIR/naked-functions.rs:173:5
99
|
1010
LL | compile_error!("this is a user specified error")
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: this is a user specified error
14-
--> $DIR/naked-functions.rs:210:5
14+
--> $DIR/naked-functions.rs:179:5
1515
|
1616
LL | compile_error!("this is a user specified error");
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

1919
error: asm template must be a string literal
20-
--> $DIR/naked-functions.rs:217:10
20+
--> $DIR/naked-functions.rs:186:10
2121
|
2222
LL | asm!(invalid_syntax)
2323
| ^^^^^^^^^^^^^^
@@ -249,42 +249,6 @@ warning: Rust ABI is unsupported in naked functions
249249
LL | pub unsafe fn rust_abi() {
250250
| ^^^^^^^^^^^^^^^^^^^^^^^^
251251

252-
error: naked functions cannot be inlined
253-
--> $DIR/naked-functions.rs:171:1
254-
|
255-
LL | #[inline]
256-
| ^^^^^^^^^
257-
258-
error: naked functions cannot be inlined
259-
--> $DIR/naked-functions.rs:178:1
260-
|
261-
LL | #[inline(always)]
262-
| ^^^^^^^^^^^^^^^^^
263-
264-
error: naked functions cannot be inlined
265-
--> $DIR/naked-functions.rs:185:1
266-
|
267-
LL | #[inline(never)]
268-
| ^^^^^^^^^^^^^^^^
269-
270-
error: naked functions cannot be inlined
271-
--> $DIR/naked-functions.rs:192:1
272-
|
273-
LL | #[inline]
274-
| ^^^^^^^^^
275-
276-
error: naked functions cannot be inlined
277-
--> $DIR/naked-functions.rs:194:1
278-
|
279-
LL | #[inline(always)]
280-
| ^^^^^^^^^^^^^^^^^
281-
282-
error: naked functions cannot be inlined
283-
--> $DIR/naked-functions.rs:196:1
284-
|
285-
LL | #[inline(never)]
286-
| ^^^^^^^^^^^^^^^^
287-
288-
error: aborting due to 33 previous errors; 2 warnings emitted
252+
error: aborting due to 27 previous errors; 2 warnings emitted
289253

290254
For more information about this error, try `rustc --explain E0787`.

0 commit comments

Comments
 (0)