Skip to content

Commit fbea191

Browse files
authored
Unrolled build for rust-lang#120944
Rollup merge of rust-lang#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 rust-lang#120940 r? ``@oli-obk`` or ``@cjgillot``
2 parents bdc1592 + 9789e88 commit fbea191

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

compiler/rustc_mir_transform/src/inline.rs

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use crate::deref_separator::deref_finder;
33
use rustc_attr::InlineAttr;
44
use rustc_const_eval::transform::validate::validate_types;
5+
use rustc_hir::def::DefKind;
56
use rustc_hir::def_id::DefId;
67
use rustc_index::bit_set::BitSet;
78
use rustc_index::Idx;
@@ -384,6 +385,17 @@ impl<'tcx> Inliner<'tcx> {
384385
}
385386

386387
let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
388+
389+
// Additionally, check that the body that we're inlining actually agrees
390+
// with the ABI of the trait that the item comes from.
391+
if let InstanceDef::Item(instance_def_id) = callee.def
392+
&& self.tcx.def_kind(instance_def_id) == DefKind::AssocFn
393+
&& let instance_fn_sig = self.tcx.fn_sig(instance_def_id).skip_binder()
394+
&& instance_fn_sig.abi() != fn_sig.abi()
395+
{
396+
return None;
397+
}
398+
387399
let source_info = SourceInfo { span: fn_span, ..terminator.source_info };
388400

389401
return Some(CallSite { callee, fn_sig, block: bb, source_info });

tests/ui/mir/inline-wrong-abi.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zmir-opt-level=0
2+
3+
#![feature(fn_traits, unboxed_closures)]
4+
struct Foo<T>(T);
5+
6+
impl<T: Copy> Fn<()> for Foo<T> {
7+
extern "C" fn call(&self, _: ()) -> T {
8+
//~^ ERROR method `call` has an incompatible type for trait
9+
match *self {
10+
Foo(t) => t,
11+
}
12+
}
13+
}
14+
15+
impl<T: Copy> FnMut<()> for Foo<T> {
16+
extern "rust-call" fn call_mut(&mut self, _: ()) -> T {
17+
self.call(())
18+
}
19+
}
20+
21+
impl<T: Copy> FnOnce<()> for Foo<T> {
22+
type Output = T;
23+
24+
extern "rust-call" fn call_once(self, _: ()) -> T {
25+
self.call(())
26+
}
27+
}
28+
29+
fn main() {
30+
let t: u8 = 1;
31+
println!("{}", Foo(t)());
32+
}

tests/ui/mir/inline-wrong-abi.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0053]: method `call` has an incompatible type for trait
2+
--> $DIR/inline-wrong-abi.rs:7:5
3+
|
4+
LL | extern "C" fn call(&self, _: ()) -> T {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "C" fn
6+
|
7+
= note: expected signature `extern "rust-call" fn(&Foo<_>, ()) -> _`
8+
found signature `extern "C" fn(&Foo<_>, ()) -> _`
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0053`.

0 commit comments

Comments
 (0)