diff options
4 files changed, 89 insertions, 12 deletions
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index f13c8214af1..8abd549c588 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -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) { diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.diff new file mode 100644 index 00000000000..c665d779e61 --- /dev/null +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.diff @@ -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]; + } + } + diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs new file mode 100644 index 00000000000..f00e99c27e4 --- /dev/null +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs @@ -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) +} diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.diff index 4fa04b05e89..34ac637af8a 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.diff @@ -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]; } } |
