Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 76aedcd

Browse files
committedMar 3, 2025·
Auto merge of rust-lang#137907 - compiler-errors:inline-fnonce, r=<try>
Inline `FnOnce`/`FnMut`/`Fn` shims once again This PR fixes the argument checking for `extern "rust-call"` ABI functions with a spread arg, which do no expect their arguments to be exploded from a tuple like closures do. Secondly, it removes the hack that prevented them from being inlined. This results in more work done by the compiler, but it does end up allowing us to inline functions we didn't before. Fixes rust-lang#137901
2 parents e16a049 + d33946c commit 76aedcd

23 files changed

+397
-123
lines changed
 

‎compiler/rustc_mir_transform/src/inline.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -606,14 +606,14 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
606606
ty::EarlyBinder::bind(callee_body.clone()),
607607
) else {
608608
debug!("failed to normalize callee body");
609-
return Err("implementation limitation");
609+
return Err("implementation limitation -- could not normalize callee body");
610610
};
611611

612612
// Normally, this shouldn't be required, but trait normalization failure can create a
613613
// validation ICE.
614614
if !validate_types(tcx, inliner.typing_env(), &callee_body, &caller_body).is_empty() {
615615
debug!("failed to validate callee body");
616-
return Err("implementation limitation");
616+
return Err("implementation limitation -- callee body failed validation");
617617
}
618618

619619
// Check call signature compatibility.
@@ -622,17 +622,9 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
622622
let output_type = callee_body.return_ty();
623623
if !util::sub_types(tcx, inliner.typing_env(), output_type, destination_ty) {
624624
trace!(?output_type, ?destination_ty);
625-
debug!("failed to normalize return type");
626-
return Err("implementation limitation");
625+
return Err("implementation limitation -- return type mismatch");
627626
}
628627
if callsite.fn_sig.abi() == ExternAbi::RustCall {
629-
// FIXME: Don't inline user-written `extern "rust-call"` functions,
630-
// since this is generally perf-negative on rustc, and we hope that
631-
// LLVM will inline these functions instead.
632-
if callee_body.spread_arg.is_some() {
633-
return Err("user-written rust-call functions");
634-
}
635-
636628
let (self_arg, arg_tuple) = match &args[..] {
637629
[arg_tuple] => (None, arg_tuple),
638630
[self_arg, arg_tuple] => (Some(self_arg), arg_tuple),
@@ -642,12 +634,17 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
642634
let self_arg_ty = self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, tcx));
643635

644636
let arg_tuple_ty = arg_tuple.node.ty(&caller_body.local_decls, tcx);
645-
let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
646-
bug!("Closure arguments are not passed as a tuple");
637+
let arg_tys = if callee_body.spread_arg.is_some() {
638+
std::slice::from_ref(&arg_tuple_ty)
639+
} else {
640+
let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
641+
bug!("Closure arguments are not passed as a tuple");
642+
};
643+
arg_tuple_tys.as_slice()
647644
};
648645

649646
for (arg_ty, input) in
650-
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
647+
self_arg_ty.into_iter().chain(arg_tys.iter().copied()).zip(callee_body.args_iter())
651648
{
652649
let input_type = callee_body.local_decls[input].ty;
653650
if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) {
@@ -663,7 +660,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
663660
if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) {
664661
trace!(?arg_ty, ?input_type);
665662
debug!("failed to normalize argument type");
666-
return Err("implementation limitation");
663+
return Err("implementation limitation -- arg mismatch");
667664
}
668665
}
669666
}
@@ -693,13 +690,13 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>(
693690
// won't cause cycles on this.
694691
if !inliner.tcx().is_mir_available(callee_def_id) {
695692
debug!("item MIR unavailable");
696-
return Err("implementation limitation");
693+
return Err("implementation limitation -- MIR unavailable");
697694
}
698695
}
699696
// These have no own callable MIR.
700697
InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => {
701698
debug!("instance without MIR (intrinsic / virtual)");
702-
return Err("implementation limitation");
699+
return Err("implementation limitation -- cannot inline intrinsic");
703700
}
704701

705702
// FIXME(#127030): `ConstParamHasTy` has bad interactions with
@@ -709,7 +706,7 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>(
709706
// substituted.
710707
InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => {
711708
debug!("still needs substitution");
712-
return Err("implementation limitation");
709+
return Err("implementation limitation -- HACK for dropping polymorphic type");
713710
}
714711

715712
// This cannot result in an immediate cycle since the callee MIR is a shim, which does
@@ -1060,8 +1057,7 @@ fn make_call_args<'tcx, I: Inliner<'tcx>>(
10601057

10611058
closure_ref_arg.chain(tuple_tmp_args).collect()
10621059
} else {
1063-
// FIXME(edition_2024): switch back to a normal method call.
1064-
<_>::into_iter(args)
1060+
args.into_iter()
10651061
.map(|a| create_temp_if_necessary(inliner, a.node, callsite, caller_body, return_block))
10661062
.collect()
10671063
}

‎tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,42 @@
77
let mut _0: ();
88
let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
99
let mut _4: I;
10+
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
11+
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
12+
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
13+
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
14+
+ }
1015

1116
bb0: {
1217
StorageLive(_3);
1318
_3 = &mut _1;
1419
StorageLive(_4);
1520
_4 = move _2;
16-
_0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable];
21+
- _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable];
22+
+ StorageLive(_6);
23+
+ StorageLive(_7);
24+
+ StorageLive(_5);
25+
+ _6 = copy (*_3);
26+
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
27+
+ _5 = &mut (*_7);
28+
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable];
1729
}
1830

1931
bb1: {
20-
StorageDead(_4);
21-
StorageDead(_3);
22-
drop(_1) -> [return: bb2, unwind unreachable];
32+
- StorageDead(_4);
33+
- StorageDead(_3);
34+
- drop(_1) -> [return: bb2, unwind unreachable];
35+
+ return;
2336
}
2437

2538
bb2: {
26-
return;
39+
- return;
40+
+ StorageDead(_5);
41+
+ StorageDead(_7);
42+
+ StorageDead(_6);
43+
+ StorageDead(_4);
44+
+ StorageDead(_3);
45+
+ drop(_1) -> [return: bb1, unwind unreachable];
2746
}
2847
}
2948

‎tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,54 @@
77
let mut _0: ();
88
let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
99
let mut _4: I;
10+
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
11+
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
12+
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
13+
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
14+
+ }
1015

1116
bb0: {
1217
StorageLive(_3);
1318
_3 = &mut _1;
1419
StorageLive(_4);
1520
_4 = move _2;
16-
_0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3];
21+
- _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3];
22+
+ StorageLive(_6);
23+
+ StorageLive(_7);
24+
+ StorageLive(_5);
25+
+ _6 = copy (*_3);
26+
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
27+
+ _5 = &mut (*_7);
28+
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb4, unwind: bb2];
1729
}
1830

1931
bb1: {
20-
StorageDead(_4);
21-
StorageDead(_3);
22-
drop(_1) -> [return: bb2, unwind: bb4];
32+
- StorageDead(_4);
33+
- StorageDead(_3);
34+
- drop(_1) -> [return: bb2, unwind: bb4];
35+
+ return;
2336
}
2437

25-
bb2: {
26-
return;
38+
- bb2: {
39+
- return;
40+
+ bb2 (cleanup): {
41+
+ drop(_1) -> [return: bb3, unwind terminate(cleanup)];
2742
}
2843

2944
bb3 (cleanup): {
30-
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
45+
- drop(_1) -> [return: bb4, unwind terminate(cleanup)];
46+
+ resume;
3147
}
3248

33-
bb4 (cleanup): {
34-
resume;
49+
- bb4 (cleanup): {
50+
- resume;
51+
+ bb4: {
52+
+ StorageDead(_5);
53+
+ StorageDead(_7);
54+
+ StorageDead(_6);
55+
+ StorageDead(_4);
56+
+ StorageDead(_3);
57+
+ drop(_1) -> [return: bb1, unwind: bb3];
3558
}
3659
}
3760

‎tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ use std::marker::Tuple;
88
// EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff
99
pub fn call<I: Tuple>(mut mock: Box<dyn FnMut<I, Output = ()>>, input: I) {
1010
// CHECK-LABEL: fn call(
11-
// CHECK-NOT: inlined
11+
// CHECK: (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut)
1212
mock.call_mut(input)
1313
}

‎tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,46 @@
77
let _2: ();
88
let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
99
let mut _4: (i32,);
10+
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
11+
+ let mut _5: &dyn std::ops::Fn(i32);
12+
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
13+
+ let mut _7: *const dyn std::ops::Fn(i32);
14+
+ }
1015

1116
bb0: {
1217
StorageLive(_2);
1318
StorageLive(_3);
1419
_3 = &_1;
1520
StorageLive(_4);
1621
_4 = (const 1_i32,);
17-
_2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
22+
- _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
23+
+ StorageLive(_6);
24+
+ StorageLive(_7);
25+
+ StorageLive(_5);
26+
+ _6 = copy (*_3);
27+
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
28+
+ _5 = &(*_7);
29+
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb2, unwind unreachable];
1830
}
1931

2032
bb1: {
33+
+ return;
34+
+ }
35+
+
36+
+ bb2: {
37+
+ StorageDead(_5);
38+
+ StorageDead(_7);
39+
+ StorageDead(_6);
2140
StorageDead(_4);
2241
StorageDead(_3);
2342
StorageDead(_2);
2443
_0 = const ();
25-
drop(_1) -> [return: bb2, unwind unreachable];
26-
}
27-
28-
bb2: {
29-
return;
44+
- drop(_1) -> [return: bb2, unwind unreachable];
45+
- }
46+
-
47+
- bb2: {
48+
- return;
49+
+ drop(_1) -> [return: bb1, unwind unreachable];
3050
}
3151
}
3252

‎tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,59 @@
77
let _2: ();
88
let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
99
let mut _4: (i32,);
10+
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
11+
+ let mut _5: &dyn std::ops::Fn(i32);
12+
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
13+
+ let mut _7: *const dyn std::ops::Fn(i32);
14+
+ }
1015

1116
bb0: {
1217
StorageLive(_2);
1318
StorageLive(_3);
1419
_3 = &_1;
1520
StorageLive(_4);
1621
_4 = (const 1_i32,);
17-
_2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3];
22+
- _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3];
23+
+ StorageLive(_6);
24+
+ StorageLive(_7);
25+
+ StorageLive(_5);
26+
+ _6 = copy (*_3);
27+
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
28+
+ _5 = &(*_7);
29+
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb4, unwind: bb2];
1830
}
1931

2032
bb1: {
21-
StorageDead(_4);
22-
StorageDead(_3);
23-
StorageDead(_2);
24-
_0 = const ();
25-
drop(_1) -> [return: bb2, unwind: bb4];
33+
- StorageDead(_4);
34+
- StorageDead(_3);
35+
- StorageDead(_2);
36+
- _0 = const ();
37+
- drop(_1) -> [return: bb2, unwind: bb4];
38+
+ return;
2639
}
2740

28-
bb2: {
29-
return;
41+
- bb2: {
42+
- return;
43+
+ bb2 (cleanup): {
44+
+ drop(_1) -> [return: bb3, unwind terminate(cleanup)];
3045
}
3146

3247
bb3 (cleanup): {
33-
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
48+
- drop(_1) -> [return: bb4, unwind terminate(cleanup)];
49+
+ resume;
3450
}
3551

36-
bb4 (cleanup): {
37-
resume;
52+
- bb4 (cleanup): {
53+
- resume;
54+
+ bb4: {
55+
+ StorageDead(_5);
56+
+ StorageDead(_7);
57+
+ StorageDead(_6);
58+
+ StorageDead(_4);
59+
+ StorageDead(_3);
60+
+ StorageDead(_2);
61+
+ _0 = const ();
62+
+ drop(_1) -> [return: bb1, unwind: bb3];
3863
}
3964
}
4065

‎tests/mir-opt/inline/inline_box_fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// EMIT_MIR inline_box_fn.call.Inline.diff
66
fn call(x: Box<dyn Fn(i32)>) {
77
// CHECK-LABEL: fn call(
8-
// CHECK-NOT: inlined
8+
// CHECK: (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call)
99
x(1);
1010
}

‎tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
let mut _0: ();
66
let _1: ();
77
+ let mut _2: fn() {f};
8+
+ let mut _4: ();
89
+ scope 1 (inlined call::<fn() {f}>) {
910
+ debug f => _2;
1011
+ let _3: ();
12+
+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) {
13+
+ scope 3 (inlined f) {
14+
+ let _5: ();
15+
+ }
16+
+ }
1117
+ }
1218

1319
bb0: {
@@ -16,10 +22,15 @@
1622
+ StorageLive(_2);
1723
+ _2 = f;
1824
+ StorageLive(_3);
19-
+ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, const ()) -> [return: bb1, unwind unreachable];
25+
+ StorageLive(_4);
26+
+ _4 = const ();
27+
+ StorageLive(_5);
28+
+ _5 = call::<fn() {f}>(f) -> [return: bb1, unwind unreachable];
2029
}
2130

2231
bb1: {
32+
+ StorageDead(_5);
33+
+ StorageDead(_4);
2334
+ StorageDead(_3);
2435
+ StorageDead(_2);
2536
StorageDead(_1);

‎tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
let mut _0: ();
66
let _1: ();
77
+ let mut _2: fn() {f};
8+
+ let mut _4: ();
89
+ scope 1 (inlined call::<fn() {f}>) {
910
+ debug f => _2;
1011
+ let _3: ();
12+
+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) {
13+
+ scope 3 (inlined f) {
14+
+ let _5: ();
15+
+ }
16+
+ }
1117
+ }
1218

1319
bb0: {
@@ -16,10 +22,15 @@
1622
+ StorageLive(_2);
1723
+ _2 = f;
1824
+ StorageLive(_3);
19-
+ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, const ()) -> [return: bb1, unwind continue];
25+
+ StorageLive(_4);
26+
+ _4 = const ();
27+
+ StorageLive(_5);
28+
+ _5 = call::<fn() {f}>(f) -> [return: bb1, unwind continue];
2029
}
2130

2231
bb1: {
32+
+ StorageDead(_5);
33+
+ StorageDead(_4);
2334
+ StorageDead(_3);
2435
+ StorageDead(_2);
2536
StorageDead(_1);

‎tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
let mut _0: ();
66
let _1: (!, !);
77
+ let mut _2: fn() -> ! {sleep};
8+
+ let mut _7: ();
89
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
910
+ debug f => _2;
1011
+ let mut _3: &fn() -> ! {sleep};
@@ -17,6 +18,10 @@
1718
+ debug b => _6;
1819
+ }
1920
+ }
21+
+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
22+
+ scope 5 (inlined sleep) {
23+
+ }
24+
+ }
2025
+ }
2126

2227
bb0: {
@@ -28,24 +33,13 @@
2833
+ StorageLive(_6);
2934
+ StorageLive(_3);
3035
+ _3 = &_2;
31-
+ _4 = <fn() -> ! {sleep} as Fn<()>>::call(move _3, const ()) -> [return: bb1, unwind unreachable];
36+
+ StorageLive(_7);
37+
+ _7 = const ();
38+
+ goto -> bb1;
3239
+ }
3340
+
3441
+ bb1: {
35-
+ StorageDead(_3);
36-
+ StorageLive(_5);
37-
+ _5 = &_2;
38-
+ _6 = <fn() -> ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb2, unwind unreachable];
39-
+ }
40-
+
41-
+ bb2: {
42-
+ StorageDead(_5);
43-
+ _1 = (copy _4, copy _6);
44-
+ drop(_2) -> [return: bb3, unwind unreachable];
45-
+ }
46-
+
47-
+ bb3: {
48-
+ unreachable;
42+
+ goto -> bb1;
4943
}
5044
}
5145

‎tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
let mut _0: ();
66
let _1: (!, !);
77
+ let mut _2: fn() -> ! {sleep};
8+
+ let mut _8: ();
89
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
910
+ debug f => _2;
1011
+ let mut _3: &fn() -> ! {sleep};
@@ -18,6 +19,10 @@
1819
+ debug b => _6;
1920
+ }
2021
+ }
22+
+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
23+
+ scope 5 (inlined sleep) {
24+
+ }
25+
+ }
2126
+ }
2227

2328
bb0: {
@@ -29,40 +34,13 @@
2934
+ StorageLive(_4);
3035
+ StorageLive(_3);
3136
+ _3 = &_2;
32-
+ _4 = <fn() -> ! {sleep} as Fn<()>>::call(move _3, const ()) -> [return: bb1, unwind: bb5];
37+
+ StorageLive(_8);
38+
+ _8 = const ();
39+
+ goto -> bb1;
3340
+ }
3441
+
3542
+ bb1: {
36-
+ StorageDead(_3);
37-
+ StorageLive(_5);
38-
+ _5 = &_2;
39-
+ _6 = <fn() -> ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb2, unwind: bb4];
40-
+ }
41-
+
42-
+ bb2: {
43-
+ StorageDead(_5);
44-
+ StorageLive(_7);
45-
+ _7 = move _4;
46-
+ _1 = (move _7, copy _6);
47-
+ StorageDead(_7);
48-
+ StorageDead(_4);
49-
+ drop(_2) -> [return: bb3, unwind continue];
50-
+ }
51-
+
52-
+ bb3: {
53-
+ unreachable;
54-
+ }
55-
+
56-
+ bb4 (cleanup): {
57-
+ drop(_4) -> [return: bb5, unwind terminate(cleanup)];
58-
+ }
59-
+
60-
+ bb5 (cleanup): {
61-
+ drop(_2) -> [return: bb6, unwind terminate(cleanup)];
62-
+ }
63-
+
64-
+ bb6 (cleanup): {
65-
+ resume;
43+
+ goto -> bb1;
6644
}
6745
}
6846

‎tests/mir-opt/inline/inline_diverging.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ pub fn g(i: i32) -> u32 {
2626
pub fn h() {
2727
// CHECK-LABEL: fn h(
2828
// CHECK: (inlined call_twice::<!, fn() -> ! {sleep}>)
29-
// CHECK-NOT: inlined
29+
// CHECK: (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep}))
30+
// CHECK: (inlined sleep)
3031
call_twice(sleep);
3132
}
3233

‎tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
let _4: fn() {foo};
1010
let mut _5: ();
1111
+ scope 1 (inlined hide_foo) {
12+
+ }
13+
+ scope 2 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) {
14+
+ scope 3 (inlined foo) {
15+
+ }
1216
+ }
1317

1418
bb0: {
@@ -23,22 +27,20 @@
2327
StorageLive(_5);
2428
_5 = ();
2529
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind unreachable];
26-
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb1, unwind unreachable];
27-
}
28-
30+
- }
31+
-
2932
- bb2: {
30-
+ bb1: {
3133
StorageDead(_5);
3234
StorageDead(_3);
3335
StorageDead(_4);
3436
StorageDead(_2);
3537
_0 = const ();
3638
- drop(_1) -> [return: bb3, unwind unreachable];
37-
+ drop(_1) -> [return: bb2, unwind unreachable];
39+
+ drop(_1) -> [return: bb1, unwind unreachable];
3840
}
3941

4042
- bb3: {
41-
+ bb2: {
43+
+ bb1: {
4244
return;
4345
}
4446
}

‎tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
let _4: fn() {foo};
1010
let mut _5: ();
1111
+ scope 1 (inlined hide_foo) {
12+
+ }
13+
+ scope 2 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) {
14+
+ scope 3 (inlined foo) {
15+
+ }
1216
+ }
1317

1418
bb0: {
@@ -23,33 +27,29 @@
2327
StorageLive(_5);
2428
_5 = ();
2529
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4];
26-
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb1, unwind: bb3];
27-
}
28-
30+
- }
31+
-
2932
- bb2: {
30-
+ bb1: {
3133
StorageDead(_5);
3234
StorageDead(_3);
3335
StorageDead(_4);
3436
StorageDead(_2);
3537
_0 = const ();
3638
- drop(_1) -> [return: bb3, unwind: bb5];
37-
+ drop(_1) -> [return: bb2, unwind: bb4];
39+
+ drop(_1) -> [return: bb1, unwind: bb2];
3840
}
3941

4042
- bb3: {
41-
+ bb2: {
43+
+ bb1: {
4244
return;
4345
}
4446

4547
- bb4 (cleanup): {
4648
- drop(_1) -> [return: bb5, unwind terminate(cleanup)];
47-
+ bb3 (cleanup): {
48-
+ drop(_1) -> [return: bb4, unwind terminate(cleanup)];
49-
}
50-
49+
- }
50+
-
5151
- bb5 (cleanup): {
52-
+ bb4 (cleanup): {
52+
+ bb2 (cleanup): {
5353
resume;
5454
}
5555
}

‎tests/mir-opt/inline/issue_78442.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ pub fn bar<P>(
99
_baz: P,
1010
) {
1111
// CHECK-LABEL: fn bar(
12-
// CHECK: let mut {{.*}}: &fn() {foo};
13-
// CHECK: let {{.*}}: fn() {foo};
1412
// CHECK: (inlined hide_foo)
15-
// CHECK-NOT: inlined
13+
// CHECK: (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo}))
14+
// CHECK: (inlined foo)
1615
hide_foo()();
1716
}
1817

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ test-mir-pass: Inline
2+
//@ compile-flags: --crate-type=lib -C panic=abort
3+
4+
// EMIT_MIR inline_fn_call_for_fn_def.test.Inline.diff
5+
6+
fn inline_fn(x: impl FnOnce() -> i32) -> i32 {
7+
x()
8+
}
9+
10+
fn yield_number() -> i32 {
11+
64
12+
}
13+
14+
fn test() -> i32 {
15+
// CHECK: (inlined inline_fn::<fn() -> i32 {yield_number}>)
16+
// CHECK: (inlined <fn() -> i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number}))
17+
// CHECK: (inlined yield_number)
18+
inline_fn(yield_number)
19+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
- // MIR for `test` before Inline
2+
+ // MIR for `test` after Inline
3+
4+
fn test() -> i32 {
5+
let mut _0: i32;
6+
-
7+
- bb0: {
8+
- _0 = inline_fn::<fn() -> i32 {yield_number}>(yield_number) -> [return: bb1, unwind unreachable];
9+
+ let mut _1: fn() -> i32 {yield_number};
10+
+ scope 1 (inlined inline_fn::<fn() -> i32 {yield_number}>) {
11+
+ let mut _2: fn() -> i32 {yield_number};
12+
+ let mut _3: ();
13+
+ scope 2 (inlined <fn() -> i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number})) {
14+
+ scope 3 (inlined yield_number) {
15+
+ }
16+
+ }
17+
}
18+
19+
- bb1: {
20+
+ bb0: {
21+
+ StorageLive(_1);
22+
+ _1 = yield_number;
23+
+ StorageLive(_2);
24+
+ _2 = move _1;
25+
+ StorageLive(_3);
26+
+ _3 = ();
27+
+ _0 = const 64_i32;
28+
+ StorageDead(_3);
29+
+ StorageDead(_2);
30+
+ StorageDead(_1);
31+
return;
32+
}
33+
}
34+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// MIR for `num_to_digit` after PreCodegen
2+
3+
fn num_to_digit(_1: char) -> u32 {
4+
debug num => _1;
5+
let mut _0: u32;
6+
let mut _4: std::option::Option<u32>;
7+
scope 1 (inlined char::methods::<impl char>::is_digit) {
8+
let _2: std::option::Option<u32>;
9+
scope 2 (inlined Option::<u32>::is_some) {
10+
let mut _3: isize;
11+
}
12+
}
13+
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
14+
let mut _5: isize;
15+
let mut _6: !;
16+
scope 4 {
17+
}
18+
}
19+
20+
bb0: {
21+
StorageLive(_2);
22+
_2 = char::methods::<impl char>::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind unreachable];
23+
}
24+
25+
bb1: {
26+
StorageLive(_3);
27+
_3 = discriminant(_2);
28+
StorageDead(_2);
29+
switchInt(move _3) -> [1: bb2, otherwise: bb7];
30+
}
31+
32+
bb2: {
33+
StorageDead(_3);
34+
StorageLive(_4);
35+
_4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
36+
}
37+
38+
bb3: {
39+
StorageLive(_5);
40+
_5 = discriminant(_4);
41+
switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6];
42+
}
43+
44+
bb4: {
45+
_6 = option::unwrap_failed() -> unwind unreachable;
46+
}
47+
48+
bb5: {
49+
_0 = move ((_4 as Some).0: u32);
50+
StorageDead(_5);
51+
StorageDead(_4);
52+
goto -> bb8;
53+
}
54+
55+
bb6: {
56+
unreachable;
57+
}
58+
59+
bb7: {
60+
StorageDead(_3);
61+
_0 = const 0_u32;
62+
goto -> bb8;
63+
}
64+
65+
bb8: {
66+
return;
67+
}
68+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// MIR for `num_to_digit` after PreCodegen
2+
3+
fn num_to_digit(_1: char) -> u32 {
4+
debug num => _1;
5+
let mut _0: u32;
6+
let mut _4: std::option::Option<u32>;
7+
scope 1 (inlined char::methods::<impl char>::is_digit) {
8+
let _2: std::option::Option<u32>;
9+
scope 2 (inlined Option::<u32>::is_some) {
10+
let mut _3: isize;
11+
}
12+
}
13+
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
14+
let mut _5: isize;
15+
let mut _6: !;
16+
scope 4 {
17+
}
18+
}
19+
20+
bb0: {
21+
StorageLive(_2);
22+
_2 = char::methods::<impl char>::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind continue];
23+
}
24+
25+
bb1: {
26+
StorageLive(_3);
27+
_3 = discriminant(_2);
28+
StorageDead(_2);
29+
switchInt(move _3) -> [1: bb2, otherwise: bb7];
30+
}
31+
32+
bb2: {
33+
StorageDead(_3);
34+
StorageLive(_4);
35+
_4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue];
36+
}
37+
38+
bb3: {
39+
StorageLive(_5);
40+
_5 = discriminant(_4);
41+
switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6];
42+
}
43+
44+
bb4: {
45+
_6 = option::unwrap_failed() -> unwind continue;
46+
}
47+
48+
bb5: {
49+
_0 = move ((_4 as Some).0: u32);
50+
StorageDead(_5);
51+
StorageDead(_4);
52+
goto -> bb8;
53+
}
54+
55+
bb6: {
56+
unreachable;
57+
}
58+
59+
bb7: {
60+
StorageDead(_3);
61+
_0 = const 0_u32;
62+
goto -> bb8;
63+
}
64+
65+
bb8: {
66+
return;
67+
}
68+
}

‎tests/mir-opt/issues/issue_59352.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
2+
// EMIT_MIR_FOR_EACH_BIT_WIDTH
3+
24
// This test is a mirror of codegen/issue-59352.rs.
35
// The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case
46
// as effectively `if x.is_some() { x.unwrap() } else { 0 }`.

‎tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
2929
let mut _12: U;
3030
scope 6 {
3131
debug x => _10;
32+
scope 7 (inlined ops::function::impls::<impl FnOnce<(T,)> for &mut impl Fn(T) -> U>::call_once) {
33+
debug self => _8;
34+
debug args => _11;
35+
}
3236
}
3337
}
3438
}
@@ -85,7 +89,7 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
8589
StorageLive(_12);
8690
StorageLive(_11);
8791
_11 = (copy _10,);
88-
_12 = <&mut impl Fn(T) -> U as FnOnce<(T,)>>::call_once(move _8, move _11) -> [return: bb7, unwind: bb10];
92+
_12 = <impl Fn(T) -> U as FnMut<(T,)>>::call_mut(move _8, move _11) -> [return: bb7, unwind: bb10];
8993
}
9094

9195
bb7: {

0 commit comments

Comments
 (0)
This repository has been archived.