Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check that the ABI of the instance we are inlining is correct #120944

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Comment on lines +389 to +397
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably check that errors have been reported, but 🤷

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we wanted to avoid depending on global state?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still figuring out the exact details on that. But we can probably invoke the wfcheck query responsible for this 😆 not really necessary tho.


let source_info = SourceInfo { span: fn_span, ..terminator.source_info };

return Some(CallSite { callee, fn_sig, block: bb, source_info });
Expand Down
32 changes: 32 additions & 0 deletions tests/ui/mir/inline-wrong-abi.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions tests/ui/mir/inline-wrong-abi.stderr
Original file line number Diff line number Diff line change
@@ -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