Only unpack tupled args in inliner if we expect args to be unpacked
This commit is contained in:
parent
2fd4c28ed7
commit
0391af0e1f
4 changed files with 89 additions and 12 deletions
|
@ -222,20 +222,23 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
trace!(?output_type, ?destination_ty);
|
trace!(?output_type, ?destination_ty);
|
||||||
return Err("failed to normalize return type");
|
return Err("failed to normalize return type");
|
||||||
}
|
}
|
||||||
if callsite.fn_sig.abi() == Abi::RustCall {
|
if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() {
|
||||||
let (arg_tuple, skipped_args) = match &args[..] {
|
let (self_arg, arg_tuple) = match &args[..] {
|
||||||
[arg_tuple] => (arg_tuple, 0),
|
[arg_tuple] => (None, arg_tuple),
|
||||||
[_, arg_tuple] => (arg_tuple, 1),
|
[self_arg, arg_tuple] => (Some(self_arg), arg_tuple),
|
||||||
_ => bug!("Expected `rust-call` to have 1 or 2 args"),
|
_ => bug!("Expected `rust-call` to have 1 or 2 args"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let self_arg_ty =
|
||||||
|
self_arg.map(|self_arg| self_arg.ty(&caller_body.local_decls, self.tcx));
|
||||||
|
|
||||||
let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx);
|
let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx);
|
||||||
let ty::Tuple(arg_tuple_tys) = arg_tuple_ty.kind() else {
|
let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else {
|
||||||
bug!("Closure arguments are not passed as a tuple");
|
bug!("Closure arguments are not passed as a tuple");
|
||||||
};
|
};
|
||||||
|
|
||||||
for (arg_ty, input) in
|
for (arg_ty, input) in
|
||||||
arg_tuple_tys.iter().zip(callee_body.args_iter().skip(skipped_args))
|
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
|
||||||
{
|
{
|
||||||
let input_type = callee_body.local_decls[input].ty;
|
let input_type = callee_body.local_decls[input].ty;
|
||||||
if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) {
|
if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
- // MIR for `call` before Inline
|
||||||
|
+ // MIR for `call` after Inline
|
||||||
|
|
||||||
|
fn call(_1: Box<dyn FnMut<I, Output = ()>>, _2: I) -> () {
|
||||||
|
debug mock => _1;
|
||||||
|
debug input => _2;
|
||||||
|
let mut _0: ();
|
||||||
|
let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
|
||||||
|
let mut _4: I;
|
||||||
|
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
|
||||||
|
+ debug self => _3;
|
||||||
|
+ debug args => _4;
|
||||||
|
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
|
||||||
|
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
|
||||||
|
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_3);
|
||||||
|
_3 = &mut _1;
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = move _2;
|
||||||
|
- _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||||
|
+ StorageLive(_5);
|
||||||
|
+ _6 = deref_copy (*_3);
|
||||||
|
+ _7 = (((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>).0: *const dyn std::ops::FnMut<I, Output = ()>);
|
||||||
|
+ _5 = &mut (*_7);
|
||||||
|
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
- StorageDead(_4);
|
||||||
|
- StorageDead(_3);
|
||||||
|
- drop(_1) -> [return: bb2, unwind unreachable];
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
- return;
|
||||||
|
+ StorageDead(_5);
|
||||||
|
+ StorageDead(_4);
|
||||||
|
+ StorageDead(_3);
|
||||||
|
+ drop(_1) -> [return: bb1, unwind unreachable];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
Normal file
10
tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// compile-flags: -Zmir-enable-passes=+Inline --crate-type=lib
|
||||||
|
|
||||||
|
#![feature(fn_traits, tuple_trait, unboxed_closures)]
|
||||||
|
|
||||||
|
use std::marker::Tuple;
|
||||||
|
|
||||||
|
// EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff
|
||||||
|
pub fn call<I: Tuple>(mut mock: Box<dyn FnMut<I, Output = ()>>, input: I) {
|
||||||
|
mock.call_mut(input)
|
||||||
|
}
|
|
@ -7,6 +7,13 @@
|
||||||
let _2: ();
|
let _2: ();
|
||||||
let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
|
let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
|
||||||
let mut _4: (i32,);
|
let mut _4: (i32,);
|
||||||
|
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
|
||||||
|
+ debug self => _3;
|
||||||
|
+ debug args => _4;
|
||||||
|
+ let mut _5: &dyn std::ops::Fn(i32);
|
||||||
|
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
|
||||||
|
+ let mut _7: *const dyn std::ops::Fn(i32);
|
||||||
|
+ }
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
|
@ -14,19 +21,30 @@
|
||||||
_3 = &_1;
|
_3 = &_1;
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = (const 1_i32,);
|
_4 = (const 1_i32,);
|
||||||
_2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
|
- _2 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||||
|
+ StorageLive(_5);
|
||||||
|
+ _6 = deref_copy (*_3);
|
||||||
|
+ _7 = (((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>).0: *const dyn std::ops::Fn(i32));
|
||||||
|
+ _5 = &(*_7);
|
||||||
|
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb2, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb2: {
|
||||||
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
_0 = const ();
|
_0 = const ();
|
||||||
drop(_1) -> [return: bb2, unwind unreachable];
|
- drop(_1) -> [return: bb2, unwind unreachable];
|
||||||
}
|
- }
|
||||||
|
-
|
||||||
bb2: {
|
- bb2: {
|
||||||
return;
|
- return;
|
||||||
|
+ drop(_1) -> [return: bb1, unwind unreachable];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue