Skip to content

Commit 0489fb0

Browse files
Rollup merge of #158814 - tahadostifam:taha_refactors_rustc_attr_parsing, r=JonathanBrouwer
Produce an error when `#[inline]` and `#[rust_force_inline]` are used together ### Merged RustcForceInline & Inline Attribute Parsers I've been reading [https://github.com/rust-lang/rust/issues/153101](https://github.com/rust-lang/rust/issues/153101), #131229 and I came across with this comment in `compiler/rustc_attr_parsing/src/attributes/inline.rs`: ```rust // FIXME(jdonszelmann): merge these two parsers and error when both attributes are present here. // note: need to model better how duplicate attr errors work when not using // SingleAttributeParser which is what we have two of here. ``` Having separate `SingleAttributeParser` implementations for `#[rustc_force_inline]` and `#[inline(...)]` meant the compiler wasn't able to recognize cases where both of them were used together on the same item, for example: ```rust #![feature(rustc_attrs)] #[rustc_force_inline] #[inline] fn foo() {} fn main() {} ``` <img width="1222" height="915" alt="image" src="https://github.com/user-attachments/assets/69d4e3b0-bc21-4679-8f3d-017f9fe152fb" /> This case was previously considered allowed, which is not correct. My changes replace the distinct attribute parsers with a single unified `AttributeParser` implementation for `InlineParser`, handling both attributes together in a single pass. By consolidating the logic, the parser now tracks the state of both attributes side-by-side using an `AcceptMapping` and introduces a new session diagnostic, `InlineForceInlineConflict`, which is explicitly triggered in the `finalize` step if a user attempts to combine them. An added benefit of catching this conflict early during the parsing phase is that it prevents downstream validation passes (like `check_attr`) from triggering redundant errors on malformed or incorrectly placed attributes, which naturally cleans up and streamlines our compiler stderr output as reflected in the updated UI test baselines. **This is my very first PR on rustc**, and I am incredibly grateful to @hkalbasi, who heavily guided me through the codebase and helped make this change possible! Sincerely looking for your feedback and thoughts on this, let me know if there is something need to be changed.
2 parents 17acbd8 + 98cc5dc commit 0489fb0

4 files changed

Lines changed: 52 additions & 4 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/inline.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
// FIXME(jdonszelmann): merge these two parsers and error when both attributes are present here.
2-
// note: need to model better how duplicate attr errors work when not using
3-
// SingleAttributeParser which is what we have two of here.
4-
51
use rustc_feature::AttributeStability;
62
use rustc_hir::attrs::{AttributeKind, InlineAttr};
3+
use rustc_hir::find_attr;
74
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
85

96
use super::prelude::*;
7+
use crate::session_diagnostics::InlineForceInlineConflict;
108

119
pub(crate) struct InlineParser;
1210

@@ -94,4 +92,16 @@ impl SingleAttributeParser for RustcForceInlineParser {
9492
cx.attr_span,
9593
))
9694
}
95+
96+
fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
97+
let Some(inline_span) = find_attr!(cx.parsed_attrs, Inline(attr, span) if !matches!(attr, InlineAttr::Force { .. }) => span)
98+
else {
99+
return;
100+
};
101+
102+
cx.emit_err(InlineForceInlineConflict {
103+
inline_span: *inline_span,
104+
force_inline_span: attr_span,
105+
});
106+
}
97107
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ use rustc_target::spec::TargetTuple;
1313
use crate::AttributeTemplate;
1414
use crate::context::Suggestion;
1515

16+
#[derive(Diagnostic)]
17+
#[diag("`#[rustc_force_inline]` and `#[inline]` cannot be used together")]
18+
pub(crate) struct InlineForceInlineConflict {
19+
#[primary_span]
20+
pub force_inline_span: Span,
21+
#[label("the inline attribute is specified here")]
22+
pub inline_span: Span,
23+
}
24+
1625
#[derive(Diagnostic)]
1726
#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)]
1827
pub(crate) struct BothFfiConstAndPure {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(rustc_attrs)]
2+
3+
#[inline] //~ NOTE: the inline attribute is specified here
4+
#[rustc_force_inline] //~ ERROR: cannot be used together
5+
fn foo() {}
6+
7+
#[rustc_force_inline] //~ ERROR: cannot be used together
8+
#[inline] //~ NOTE: the inline attribute is specified here
9+
fn bar() {}
10+
11+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: `#[rustc_force_inline]` and `#[inline]` cannot be used together
2+
--> $DIR/rustc-force-inline-conflict-with-inline.rs:4:1
3+
|
4+
LL | #[inline]
5+
| --------- the inline attribute is specified here
6+
LL | #[rustc_force_inline]
7+
| ^^^^^^^^^^^^^^^^^^^^^
8+
9+
error: `#[rustc_force_inline]` and `#[inline]` cannot be used together
10+
--> $DIR/rustc-force-inline-conflict-with-inline.rs:7:1
11+
|
12+
LL | #[rustc_force_inline]
13+
| ^^^^^^^^^^^^^^^^^^^^^
14+
LL | #[inline]
15+
| --------- the inline attribute is specified here
16+
17+
error: aborting due to 2 previous errors
18+

0 commit comments

Comments
 (0)