Skip to content

Commit 238ff75

Browse files
committed
Auto merge of rust-lang#137915 - compiler-errors:inliner-experiment-2, r=<try>
[do not merge] Inliner experiment 2 cc rust-lang#137907 (comment) r? `@ghost`
2 parents daf5985 + 2ef6f1d commit 238ff75

File tree

4 files changed

+52
-61
lines changed

4 files changed

+52
-61
lines changed

compiler/rustc_mir_transform/src/inline.rs

+20-18
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,15 +622,13 @@ 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");
628+
match callsite.callee.def {
629+
InstanceKind::Item(def_id) if tcx.is_closure_like(def_id) => {}
630+
InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } => {}
631+
_ => return Err("not inlining non-builtin call"),
634632
}
635633

636634
let (self_arg, arg_tuple) = match &args[..] {
@@ -642,12 +640,17 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
642640
let self_arg_ty = self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, tcx));
643641

644642
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");
643+
let arg_tys = if callee_body.spread_arg.is_some() {
644+
std::slice::from_ref(&arg_tuple_ty)
645+
} else {
646+
let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
647+
bug!("Closure arguments are not passed as a tuple");
648+
};
649+
arg_tuple_tys.as_slice()
647650
};
648651

649652
for (arg_ty, input) in
650-
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
653+
self_arg_ty.into_iter().chain(arg_tys.iter().copied()).zip(callee_body.args_iter())
651654
{
652655
let input_type = callee_body.local_decls[input].ty;
653656
if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) {
@@ -663,7 +666,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>(
663666
if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) {
664667
trace!(?arg_ty, ?input_type);
665668
debug!("failed to normalize argument type");
666-
return Err("implementation limitation");
669+
return Err("implementation limitation -- arg mismatch");
667670
}
668671
}
669672
}
@@ -693,13 +696,13 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>(
693696
// won't cause cycles on this.
694697
if !inliner.tcx().is_mir_available(callee_def_id) {
695698
debug!("item MIR unavailable");
696-
return Err("implementation limitation");
699+
return Err("implementation limitation -- MIR unavailable");
697700
}
698701
}
699702
// These have no own callable MIR.
700703
InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => {
701704
debug!("instance without MIR (intrinsic / virtual)");
702-
return Err("implementation limitation");
705+
return Err("implementation limitation -- cannot inline intrinsic");
703706
}
704707

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

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

10611064
closure_ref_arg.chain(tuple_tmp_args).collect()
10621065
} else {
1063-
// FIXME(edition_2024): switch back to a normal method call.
1064-
<_>::into_iter(args)
1066+
args.into_iter()
10651067
.map(|a| create_temp_if_necessary(inliner, a.node, callsite, caller_body, return_block))
10661068
.collect()
10671069
}

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

+12-1
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-unwind.diff

+9-31
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/issue_78442.bar.Inline.panic-unwind.diff

+11-11
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
}

0 commit comments

Comments
 (0)