Extends rustc_force_inline to inherent methods

- Changes parser to allow application to inherent methods.
- Adds tests to confirm extended functionality works just as the existing.
This commit is contained in:
Reuben Cruise 2025-09-25 16:11:34 +01:00
parent caccb4d036
commit 5bf5e71160
20 changed files with 346 additions and 25 deletions

View file

@ -72,7 +72,11 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
const PATH: &'static [Symbol] = &[sym::rustc_force_inline];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Method(MethodKind::Inherent)),
]);
const TEMPLATE: AttributeTemplate = template!(Word, List: &["reason"], NameValueStr: "reason");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {

View file

@ -0,0 +1,21 @@
- // MIR for `caller::{closure#0}` before ForceInline
+ // MIR for `caller::{closure#0}` after ForceInline
fn caller::{closure#0}(_1: &{closure@$DIR/forced_closure_inherent.rs:14:6: 14:8}) -> () {
let mut _0: ();
let _2: ();
+ scope 1 (inlined Foo::callee_forced) {
+ }
bb0: {
StorageLive(_2);
- _2 = Foo::callee_forced() -> [return: bb1, unwind unreachable];
- }
-
- bb1: {
StorageDead(_2);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller::{closure#0}` before ForceInline
+ // MIR for `caller::{closure#0}` after ForceInline
fn caller::{closure#0}(_1: &{closure@$DIR/forced_closure_inherent.rs:14:6: 14:8}) -> () {
let mut _0: ();
let _2: ();
+ scope 1 (inlined Foo::callee_forced) {
+ }
bb0: {
StorageLive(_2);
- _2 = Foo::callee_forced() -> [return: bb1, unwind continue];
- }
-
- bb1: {
StorageDead(_2);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,19 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ compile-flags: -Copt-level=0 --crate-type=lib
#![feature(rustc_attrs)]
struct Foo {}
impl Foo {
#[rustc_force_inline]
pub fn callee_forced() {}
}
// EMIT_MIR forced_closure_inherent.caller-{closure#0}.ForceInline.diff
pub fn caller() {
(|| {
Foo::callee_forced();
// CHECK-LABEL: fn caller::{closure#0}(
// CHECK: (inlined Foo::callee_forced)
})();
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> () {
let mut _0: ();
let _1: ();
+ scope 1 (inlined Foo::bar) {
+ }
bb0: {
StorageLive(_1);
- _1 = Foo::bar() -> [return: bb1, unwind unreachable];
- }
-
- bb1: {
StorageDead(_1);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> () {
let mut _0: ();
let _1: ();
+ scope 1 (inlined Foo::bar) {
+ }
bb0: {
StorageLive(_1);
- _1 = Foo::bar() -> [return: bb1, unwind continue];
- }
-
- bb1: {
StorageDead(_1);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,17 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ compile-flags: -Copt-level=0 --crate-type=lib
#![feature(rustc_attrs)]
struct Foo;
impl Foo {
#[rustc_force_inline]
fn bar() {}
}
// EMIT_MIR forced_inherent.caller.ForceInline.diff
fn caller() {
Foo::bar();
// CHECK-LABEL: fn caller(
// CHECK: (inlined Foo::bar)
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> () {
let mut _0: ();
let _1: ();
+ scope 1 (inlined Foo::bar) {
+ }
bb0: {
StorageLive(_1);
- _1 = Foo::bar() -> [return: bb1, unwind unreachable];
- }
-
- bb1: {
StorageDead(_1);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> () {
let mut _0: ();
let _1: ();
+ scope 1 (inlined Foo::bar) {
+ }
bb0: {
StorageLive(_1);
- _1 = Foo::bar() -> [return: bb1, unwind continue];
- }
-
- bb1: {
StorageDead(_1);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,25 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ compile-flags: -Copt-level=0 --crate-type=lib
#![feature(rustc_attrs)]
struct Foo;
impl Foo {
#[rustc_force_inline]
fn bar() {}
}
trait Tr {
fn bar();
}
impl Tr for Foo {
fn bar() {}
}
// EMIT_MIR forced_inherent_ambiguous.caller.ForceInline.diff
fn caller() {
Foo::bar();
// CHECK-LABEL: fn caller(
// CHECK: (inlined Foo::bar)
}

View file

@ -0,0 +1,12 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> {async fn body of caller()} {
let mut _0: {async fn body of caller()};
bb0: {
_0 = {coroutine@$DIR/forced_inherent_async.rs:14:19: 18:2 (#0)};
return;
}
}

View file

@ -0,0 +1,12 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> {async fn body of caller()} {
let mut _0: {async fn body of caller()};
bb0: {
_0 = {coroutine@$DIR/forced_inherent_async.rs:14:19: 18:2 (#0)};
return;
}
}

View file

@ -0,0 +1,18 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ compile-flags: -Copt-level=0 --crate-type=lib
//@ edition: 2021
#![feature(rustc_attrs)]
struct Foo {}
impl Foo {
#[rustc_force_inline]
pub fn callee_forced() {}
}
// EMIT_MIR forced_inherent_async.caller.ForceInline.diff
async fn caller() {
Foo::callee_forced();
// CHECK-LABEL: fn caller(
// CHECK: (inlined Foo::callee_forced)
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> () {
let mut _0: ();
let _1: ();
+ scope 1 (inlined Foo::callee_forced) {
+ }
bb0: {
StorageLive(_1);
- _1 = Foo::callee_forced() -> [return: bb1, unwind unreachable];
- }
-
- bb1: {
StorageDead(_1);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,21 @@
- // MIR for `caller` before ForceInline
+ // MIR for `caller` after ForceInline
fn caller() -> () {
let mut _0: ();
let _1: ();
+ scope 1 (inlined Foo::callee_forced) {
+ }
bb0: {
StorageLive(_1);
- _1 = Foo::callee_forced() -> [return: bb1, unwind continue];
- }
-
- bb1: {
StorageDead(_1);
_0 = const ();
return;
}
}

View file

@ -0,0 +1,21 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ compile-flags: -Copt-level=0 -Clink-dead-code
#![feature(rustc_attrs)]
struct Foo {}
impl Foo {
#[rustc_force_inline]
pub fn callee_forced() {}
}
// EMIT_MIR forced_inherent_dead_code.caller.ForceInline.diff
pub fn caller() {
Foo::callee_forced();
// CHECK-LABEL: fn caller(
// CHECK: (inlined Foo::callee_forced)
}
fn main() {
caller();
}

View file

@ -0,0 +1,21 @@
//@ check-fail
#![feature(rustc_attrs)]
struct Foo;
impl Foo {
#[rustc_force_inline]
//~^ ERROR: `Foo::bar` is incompatible with `#[rustc_force_inline]`
#[rustc_no_mir_inline]
fn bar() {}
}
fn bar_caller() {
unsafe {
Foo::bar();
}
}
fn main() {
bar_caller();
}

View file

@ -0,0 +1,13 @@
error: `Foo::bar` is incompatible with `#[rustc_force_inline]`
--> $DIR/inherent.rs:7:5
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
...
LL | fn bar() {}
| -------- `Foo::bar` defined here
|
= note: incompatible due to: #[rustc_no_mir_inline]
error: aborting due to 1 previous error

View file

@ -114,7 +114,6 @@ trait FooQux = FooBaz;
//~^ ERROR attribute cannot be used on
impl<T> Bar<T> {
#[rustc_force_inline]
//~^ ERROR attribute cannot be used on
fn foo() {}
}

View file

@ -1,5 +1,5 @@
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
--> $DIR/invalid.rs:132:11
--> $DIR/invalid.rs:131:11
|
LL | fn barqux(#[rustc_force_inline] _x: u32) {}
| ^^^^^^^^^^^^^^^^^^^^^
@ -134,7 +134,7 @@ error: `#[rustc_force_inline]` attribute cannot be used on foreign functions
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[rustc_force_inline]` can only be applied to functions
= help: `#[rustc_force_inline]` can be applied to functions and inherent methods
error: `#[rustc_force_inline]` attribute cannot be used on type aliases
--> $DIR/invalid.rs:66:1
@ -222,7 +222,7 @@ error: `#[rustc_force_inline]` attribute cannot be used on provided trait method
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[rustc_force_inline]` can only be applied to functions
= help: `#[rustc_force_inline]` can be applied to functions and inherent methods
error: `#[rustc_force_inline]` attribute cannot be used on trait aliases
--> $DIR/invalid.rs:109:1
@ -240,16 +240,8 @@ LL | #[rustc_force_inline]
|
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on inherent methods
--> $DIR/invalid.rs:116:5
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on trait impl blocks
--> $DIR/invalid.rs:121:1
--> $DIR/invalid.rs:120:1
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -257,7 +249,7 @@ LL | #[rustc_force_inline]
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on macro defs
--> $DIR/invalid.rs:128:1
--> $DIR/invalid.rs:127:1
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -265,7 +257,7 @@ LL | #[rustc_force_inline]
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on function params
--> $DIR/invalid.rs:132:11
--> $DIR/invalid.rs:131:11
|
LL | fn barqux(#[rustc_force_inline] _x: u32) {}
| ^^^^^^^^^^^^^^^^^^^^^
@ -273,15 +265,15 @@ LL | fn barqux(#[rustc_force_inline] _x: u32) {}
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on closures
--> $DIR/invalid.rs:149:14
--> $DIR/invalid.rs:148:14
|
LL | let _x = #[rustc_force_inline] || { };
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[rustc_force_inline]` can only be applied to functions
= help: `#[rustc_force_inline]` can be applied to functions and inherent methods
error: `#[rustc_force_inline]` attribute cannot be used on expressions
--> $DIR/invalid.rs:151:14
--> $DIR/invalid.rs:150:14
|
LL | let _y = #[rustc_force_inline] 3 + 4;
| ^^^^^^^^^^^^^^^^^^^^^
@ -289,7 +281,7 @@ LL | let _y = #[rustc_force_inline] 3 + 4;
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on statements
--> $DIR/invalid.rs:153:5
--> $DIR/invalid.rs:152:5
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -297,7 +289,7 @@ LL | #[rustc_force_inline]
= help: `#[rustc_force_inline]` can only be applied to functions
error: `#[rustc_force_inline]` attribute cannot be used on match arms
--> $DIR/invalid.rs:158:9
--> $DIR/invalid.rs:157:9
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -305,7 +297,7 @@ LL | #[rustc_force_inline]
= help: `#[rustc_force_inline]` can only be applied to functions
error: attribute cannot be applied to a `async`, `gen` or `async gen` function
--> $DIR/invalid.rs:136:1
--> $DIR/invalid.rs:135:1
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -314,7 +306,7 @@ LL | async fn async_foo() {}
| -------------------- `async`, `gen` or `async gen` function
error: attribute cannot be applied to a `async`, `gen` or `async gen` function
--> $DIR/invalid.rs:140:1
--> $DIR/invalid.rs:139:1
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -323,7 +315,7 @@ LL | gen fn gen_foo() {}
| ---------------- `async`, `gen` or `async gen` function
error: attribute cannot be applied to a `async`, `gen` or `async gen` function
--> $DIR/invalid.rs:144:1
--> $DIR/invalid.rs:143:1
|
LL | #[rustc_force_inline]
| ^^^^^^^^^^^^^^^^^^^^^
@ -331,7 +323,7 @@ LL |
LL | async gen fn async_gen_foo() {}
| ---------------------------- `async`, `gen` or `async gen` function
error: aborting due to 37 previous errors
error: aborting due to 36 previous errors
Some errors have detailed explanations: E0539, E0805.
For more information about an error, try `rustc --explain E0539`.