Don't inline functions with unsized args
This commit is contained in:
parent
fe76e14955
commit
60cc72cf7b
@ -168,6 +168,18 @@ fn try_inlining(
|
||||
) -> Result<std::ops::Range<BasicBlock>, &'static str> {
|
||||
let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
|
||||
self.check_codegen_attributes(callsite, callee_attrs)?;
|
||||
|
||||
let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
|
||||
let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
|
||||
let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
|
||||
for arg in args {
|
||||
if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
|
||||
// We do not allow inlining functions with unsized params. Inlining these functions
|
||||
// could create unsized locals, which are unsound and being phased out.
|
||||
return Err("Call has unsized argument");
|
||||
}
|
||||
}
|
||||
|
||||
self.check_mir_is_available(caller_body, &callsite.callee)?;
|
||||
let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?;
|
||||
self.check_mir_body(callsite, callee_body, callee_attrs)?;
|
||||
@ -189,9 +201,6 @@ fn try_inlining(
|
||||
// Check call signature compatibility.
|
||||
// Normally, this shouldn't be required, but trait normalization failure can create a
|
||||
// validation ICE.
|
||||
let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
|
||||
let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
|
||||
let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
|
||||
let output_type = callee_body.return_ty();
|
||||
if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) {
|
||||
trace!(?output_type, ?destination_ty);
|
||||
|
50
tests/mir-opt/inline/unsized_argument.caller.Inline.diff
Normal file
50
tests/mir-opt/inline/unsized_argument.caller.Inline.diff
Normal file
@ -0,0 +1,50 @@
|
||||
- // MIR for `caller` before Inline
|
||||
+ // MIR for `caller` after Inline
|
||||
|
||||
fn caller(_1: Box<[i32]>) -> () {
|
||||
debug x => _1; // in scope 0 at $DIR/unsized_argument.rs:+0:11: +0:12
|
||||
let mut _0: (); // return place in scope 0 at $DIR/unsized_argument.rs:+0:26: +0:26
|
||||
let _2: (); // in scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
|
||||
let mut _3: std::boxed::Box<[i32]>; // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
|
||||
let mut _4: (); // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
|
||||
let mut _5: (); // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
|
||||
let mut _6: (); // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
|
||||
let mut _7: *const [i32]; // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
|
||||
StorageLive(_3); // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
|
||||
_3 = move _1; // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
|
||||
_7 = (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]); // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
|
||||
_2 = callee(move (*_7)) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
|
||||
// mir::Constant
|
||||
// + span: $DIR/unsized_argument.rs:9:5: 9:11
|
||||
// + literal: Const { ty: fn([i32]) {callee}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3); // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
|
||||
StorageDead(_2); // scope 0 at $DIR/unsized_argument.rs:+1:15: +1:16
|
||||
_0 = const (); // scope 0 at $DIR/unsized_argument.rs:+0:26: +2:2
|
||||
return; // scope 0 at $DIR/unsized_argument.rs:+2:2: +2:2
|
||||
}
|
||||
|
||||
bb2 (cleanup): {
|
||||
resume; // scope 0 at $DIR/unsized_argument.rs:+0:1: +2:2
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_4 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> bb1; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
|
||||
// mir::Constant
|
||||
// + span: $DIR/unsized_argument.rs:9:14: 9:15
|
||||
// + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
bb4 (cleanup): {
|
||||
_6 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> [return: bb2, unwind terminate]; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
|
||||
// mir::Constant
|
||||
// + span: $DIR/unsized_argument.rs:9:14: 9:15
|
||||
// + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
|
||||
}
|
||||
}
|
||||
|
15
tests/mir-opt/inline/unsized_argument.rs
Normal file
15
tests/mir-opt/inline/unsized_argument.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// needs-unwind
|
||||
#![feature(unsized_fn_params)]
|
||||
|
||||
#[inline(always)]
|
||||
fn callee(y: [i32]) {}
|
||||
|
||||
// EMIT_MIR unsized_argument.caller.Inline.diff
|
||||
fn caller(x: Box<[i32]>) {
|
||||
callee(*x);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = Box::new([1]);
|
||||
caller(b);
|
||||
}
|
Loading…
Reference in New Issue
Block a user