mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Rollup merge of #120944 - compiler-errors:inliner-abi, r=oli-obk
Check that the ABI of the instance we are inlining is correct When computing the `CallSite` in the mir inliner, double check that the instance of the function that we are inlining is compatible with the signature from the trait definition that we acquire from the MIR. Fixes #120940 r? ``@oli-obk`` or ``@cjgillot``
This commit is contained in:
commit
8ec144d738
@ -2,6 +2,7 @@
|
||||
use crate::deref_separator::deref_finder;
|
||||
use rustc_attr::InlineAttr;
|
||||
use rustc_const_eval::transform::validate::validate_types;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::Idx;
|
||||
@ -384,6 +385,17 @@ impl<'tcx> Inliner<'tcx> {
|
||||
}
|
||||
|
||||
let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
|
||||
|
||||
// Additionally, check that the body that we're inlining actually agrees
|
||||
// with the ABI of the trait that the item comes from.
|
||||
if let InstanceDef::Item(instance_def_id) = callee.def
|
||||
&& self.tcx.def_kind(instance_def_id) == DefKind::AssocFn
|
||||
&& let instance_fn_sig = self.tcx.fn_sig(instance_def_id).skip_binder()
|
||||
&& instance_fn_sig.abi() != fn_sig.abi()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let source_info = SourceInfo { span: fn_span, ..terminator.source_info };
|
||||
|
||||
return Some(CallSite { callee, fn_sig, block: bb, source_info });
|
||||
|
32
tests/ui/mir/inline-wrong-abi.rs
Normal file
32
tests/ui/mir/inline-wrong-abi.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zmir-opt-level=0
|
||||
|
||||
#![feature(fn_traits, unboxed_closures)]
|
||||
struct Foo<T>(T);
|
||||
|
||||
impl<T: Copy> Fn<()> for Foo<T> {
|
||||
extern "C" fn call(&self, _: ()) -> T {
|
||||
//~^ ERROR method `call` has an incompatible type for trait
|
||||
match *self {
|
||||
Foo(t) => t,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> FnMut<()> for Foo<T> {
|
||||
extern "rust-call" fn call_mut(&mut self, _: ()) -> T {
|
||||
self.call(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> FnOnce<()> for Foo<T> {
|
||||
type Output = T;
|
||||
|
||||
extern "rust-call" fn call_once(self, _: ()) -> T {
|
||||
self.call(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let t: u8 = 1;
|
||||
println!("{}", Foo(t)());
|
||||
}
|
12
tests/ui/mir/inline-wrong-abi.stderr
Normal file
12
tests/ui/mir/inline-wrong-abi.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0053]: method `call` has an incompatible type for trait
|
||||
--> $DIR/inline-wrong-abi.rs:7:5
|
||||
|
|
||||
LL | extern "C" fn call(&self, _: ()) -> T {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "C" fn
|
||||
|
|
||||
= note: expected signature `extern "rust-call" fn(&Foo<_>, ()) -> _`
|
||||
found signature `extern "C" fn(&Foo<_>, ()) -> _`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0053`.
|
Loading…
Reference in New Issue
Block a user