Only unpack tupled args in inliner if we expect args to be unpacked
This commit is contained in:
parent
2fd4c28ed7
commit
0391af0e1f
@ -222,20 +222,23 @@ impl<'tcx> Inliner<'tcx> {
|
||||
trace!(?output_type, ?destination_ty);
|
||||
return Err("failed to normalize return type");
|
||||
}
|
||||
if callsite.fn_sig.abi() == Abi::RustCall {
|
||||
let (arg_tuple, skipped_args) = match &args[..] {
|
||||
[arg_tuple] => (arg_tuple, 0),
|
||||
[_, arg_tuple] => (arg_tuple, 1),
|
||||
if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() {
|
||||
let (self_arg, arg_tuple) = match &args[..] {
|
||||
[arg_tuple] => (None, arg_tuple),
|
||||
[self_arg, arg_tuple] => (Some(self_arg), arg_tuple),
|
||||
_ => 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 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");
|
||||
};
|
||||
|
||||
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;
|
||||
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 mut _3: &std::boxed::Box<dyn std::ops::Fn(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: {
|
||||
StorageLive(_2);
|
||||
@ -14,19 +21,30 @@
|
||||
_3 = &_1;
|
||||
StorageLive(_4);
|
||||
_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: {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bb2: {
|
||||
+ StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
StorageDead(_3);
|
||||
StorageDead(_2);
|
||||
_0 = const ();
|
||||
drop(_1) -> [return: bb2, unwind unreachable];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
return;
|
||||
- drop(_1) -> [return: bb2, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
- return;
|
||||
+ drop(_1) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user