Skip inlining if there are normalization issues.
This commit is contained in:
parent
0161ecd13f
commit
ce4b5c8afc
5 changed files with 97 additions and 61 deletions
|
@ -1,6 +1,7 @@
|
||||||
//! Inlining pass for MIR functions
|
//! Inlining pass for MIR functions
|
||||||
use crate::deref_separator::deref_finder;
|
use crate::deref_separator::deref_finder;
|
||||||
use rustc_attr::InlineAttr;
|
use rustc_attr::InlineAttr;
|
||||||
|
use rustc_const_eval::transform::validate::equal_up_to_regions;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
|
@ -166,6 +167,45 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
return Err("failed to normalize callee body");
|
return Err("failed to normalize callee body");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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 !equal_up_to_regions(self.tcx, self.param_env, output_type, destination_ty) {
|
||||||
|
trace!(?output_type, ?destination_ty);
|
||||||
|
return Err("failed to normalize return type");
|
||||||
|
}
|
||||||
|
if callsite.fn_sig.abi() == Abi::RustCall {
|
||||||
|
let mut args = args.into_iter();
|
||||||
|
let _ = args.next(); // Skip `self` argument.
|
||||||
|
let arg_tuple_ty = args.next().unwrap().ty(&caller_body.local_decls, self.tcx);
|
||||||
|
assert!(args.next().is_none());
|
||||||
|
|
||||||
|
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(1)) {
|
||||||
|
let input_type = callee_body.local_decls[input].ty;
|
||||||
|
if !equal_up_to_regions(self.tcx, self.param_env, arg_ty, input_type) {
|
||||||
|
trace!(?arg_ty, ?input_type);
|
||||||
|
return Err("failed to normalize tuple argument type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
|
||||||
|
let input_type = callee_body.local_decls[input].ty;
|
||||||
|
let arg_ty = arg.ty(&caller_body.local_decls, self.tcx);
|
||||||
|
if !equal_up_to_regions(self.tcx, self.param_env, arg_ty, input_type) {
|
||||||
|
trace!(?arg_ty, ?input_type);
|
||||||
|
return Err("failed to normalize argument type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let old_blocks = caller_body.basic_blocks().next_index();
|
let old_blocks = caller_body.basic_blocks().next_index();
|
||||||
self.inline_call(caller_body, &callsite, callee_body);
|
self.inline_call(caller_body, &callsite, callee_body);
|
||||||
let new_blocks = old_blocks..caller_body.basic_blocks().next_index();
|
let new_blocks = old_blocks..caller_body.basic_blocks().next_index();
|
||||||
|
|
24
src/test/mir-opt/inline/caller-with-trivial-bound.rs
Normal file
24
src/test/mir-opt/inline/caller-with-trivial-bound.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
pub trait Factory<T> {
|
||||||
|
type Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IntFactory;
|
||||||
|
|
||||||
|
impl<T> Factory<T> for IntFactory {
|
||||||
|
type Item = usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR caller_with_trivial_bound.foo.Inline.diff
|
||||||
|
pub fn foo<T>()
|
||||||
|
where
|
||||||
|
IntFactory: Factory<T>,
|
||||||
|
{
|
||||||
|
let mut x: <IntFactory as Factory<T>>::Item = bar::<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn bar<T>() -> <IntFactory as Factory<T>>::Item {
|
||||||
|
0usize
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
- // MIR for `foo` before Inline
|
||||||
|
+ // MIR for `foo` after Inline
|
||||||
|
|
||||||
|
fn foo() -> () {
|
||||||
|
let mut _0: (); // return place in scope 0 at $DIR/caller-with-trivial-bound.rs:15:1: 15:1
|
||||||
|
let mut _1: <IntFactory as Factory<T>>::Item; // in scope 0 at $DIR/caller-with-trivial-bound.rs:18:9: 18:14
|
||||||
|
scope 1 {
|
||||||
|
debug x => _1; // in scope 1 at $DIR/caller-with-trivial-bound.rs:18:9: 18:14
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1); // scope 0 at $DIR/caller-with-trivial-bound.rs:18:9: 18:14
|
||||||
|
_1 = bar::<T>() -> bb1; // scope 0 at $DIR/caller-with-trivial-bound.rs:18:51: 18:61
|
||||||
|
// mir::Constant
|
||||||
|
// + span: $DIR/caller-with-trivial-bound.rs:18:51: 18:59
|
||||||
|
// + literal: Const { ty: fn() -> <IntFactory as Factory<T>>::Item {bar::<T>}, val: Value(Scalar(<ZST>)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
_0 = const (); // scope 0 at $DIR/caller-with-trivial-bound.rs:17:1: 19:2
|
||||||
|
drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/caller-with-trivial-bound.rs:19:1: 19:2
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageDead(_1); // scope 0 at $DIR/caller-with-trivial-bound.rs:19:1: 19:2
|
||||||
|
return; // scope 0 at $DIR/caller-with-trivial-bound.rs:19:2: 19:2
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3 (cleanup): {
|
||||||
|
resume; // scope 0 at $DIR/caller-with-trivial-bound.rs:14:1: 19:2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
// known-bug: #93008
|
|
||||||
// build-fail
|
|
||||||
// failure-status: 101
|
|
||||||
// compile-flags:--crate-type=lib -Zmir-opt-level=3
|
|
||||||
// rustc-env:RUST_BACKTRACE=0
|
|
||||||
|
|
||||||
// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked"
|
|
||||||
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
|
|
||||||
// normalize-stderr-test "error: internal compiler error.*" -> "error: internal compiler error"
|
|
||||||
// normalize-stderr-test "encountered.*with incompatible types:" "encountered ... with incompatible types:"
|
|
||||||
// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
|
|
||||||
// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
|
|
||||||
// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
|
|
||||||
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
|
|
||||||
// normalize-stderr-test "query stack during panic:\n" -> ""
|
|
||||||
// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
|
|
||||||
// normalize-stderr-test "end of query stack\n" -> ""
|
|
||||||
// normalize-stderr-test "#.*\n" -> ""
|
|
||||||
|
|
||||||
// This is a known bug that @compiler-errors tried to fix in #94238,
|
|
||||||
// but the solution was probably not correct.
|
|
||||||
|
|
||||||
pub trait Factory<T> {
|
|
||||||
type Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IntFactory;
|
|
||||||
|
|
||||||
impl<T> Factory<T> for IntFactory {
|
|
||||||
type Item = usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn foo<T>()
|
|
||||||
where
|
|
||||||
IntFactory: Factory<T>,
|
|
||||||
{
|
|
||||||
let mut x: <IntFactory as Factory<T>>::Item = bar::<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn bar<T>() -> <IntFactory as Factory<T>>::Item {
|
|
||||||
0usize
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
error: internal compiler error
|
|
||||||
|
|
||||||
error: internal compiler error
|
|
||||||
encountered ... with incompatible types:
|
|
||||||
left-hand side has type: <IntFactory as Factory<T>>::Item
|
|
||||||
right-hand side has type: usize
|
|
||||||
--> $DIR/select-param-env-instead-of-blanket.rs:42:5
|
|
||||||
|
|
|
||||||
LL | let mut x: <IntFactory as Factory<T>>::Item = bar::<T>();
|
|
||||||
| ---------- in this inlined function call
|
|
||||||
...
|
|
||||||
LL | 0usize
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
= note: delayed at compiler/rustc_const_eval/src/transform/validate.rs:128:36
|
|
||||||
|
|
||||||
thread 'rustc' panicked
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue