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

Rustup #3046

Merged
merged 8 commits into from
Aug 31, 2023
Merged

Rustup #3046

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
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
008c21c9779fd1e3632d9fe908b8afc0c421b26c
dca2d1ff00bf96d244b1bb9a2117a92ec50ac71d
16 changes: 16 additions & 0 deletions tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![feature(portable_simd)]

// Some targets treat arrays and structs very differently. We would probably catch that on those
// targets since we check the `PassMode`; here we ensure that we catch it on *all* targets
// (in particular, on x86-64 the pass mode is `Indirect` for both of these).
struct S(i32, i32, i32, i32);
type A = [i32; 4];

fn main() {
fn f(_: S) {}

// These two types have the same size but are still not compatible.
let g = unsafe { std::mem::transmute::<fn(S), fn(A)>(f) };

g(Default::default()) //~ ERROR: calling a function with argument of type S passing data of type [i32; 4]
}
15 changes: 15 additions & 0 deletions tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: calling a function with argument of type S passing data of type [i32; 4]
--> $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
|
LL | g(Default::default())
| ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S passing data of type [i32; 4]
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to previous error

7 changes: 7 additions & 0 deletions tests/fail/function_pointers/abi_mismatch_int_vs_float.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
fn f(_: f32) {}

let g = unsafe { std::mem::transmute::<fn(f32), fn(i32)>(f) };

g(42) //~ ERROR: calling a function with argument of type f32 passing data of type i32
}
15 changes: 15 additions & 0 deletions tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: calling a function with argument of type f32 passing data of type i32
--> $DIR/abi_mismatch_int_vs_float.rs:LL:CC
|
LL | g(42)
| ^^^^^ calling a function with argument of type f32 passing data of type i32
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: calling a function with argument of type *const [i32] passing data of type *const i32
--> $DIR/cast_fn_ptr4.rs:LL:CC
--> $DIR/abi_mismatch_raw_pointer.rs:LL:CC
|
LL | g(&42 as *const i32)
| ^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type *const [i32] passing data of type *const i32
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/cast_fn_ptr4.rs:LL:CC
= note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: calling a function with return type u32 passing return place of type ()
--> $DIR/cast_fn_ptr5.rs:LL:CC
--> $DIR/abi_mismatch_return_type.rs:LL:CC
|
LL | g()
| ^^^ calling a function with return type u32 passing return place of type ()
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/cast_fn_ptr5.rs:LL:CC
= note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: calling a function with argument of type (i32, i32) passing data of type i32
--> $DIR/cast_fn_ptr2.rs:LL:CC
--> $DIR/abi_mismatch_simple.rs:LL:CC
|
LL | g(42)
| ^^^^^ calling a function with argument of type (i32, i32) passing data of type i32
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/cast_fn_ptr2.rs:LL:CC
= note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: calling a function with fewer arguments than it requires
--> $DIR/cast_fn_ptr3.rs:LL:CC
--> $DIR/abi_mismatch_too_few_args.rs:LL:CC
|
LL | g()
| ^^^ calling a function with fewer arguments than it requires
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/cast_fn_ptr3.rs:LL:CC
= note: inside `main` at $DIR/abi_mismatch_too_few_args.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error: Undefined Behavior: calling a function with more arguments than it expected
--> $DIR/cast_fn_ptr1.rs:LL:CC
--> $DIR/abi_mismatch_too_many_args.rs:LL:CC
|
LL | g(42)
| ^^^^^ calling a function with more arguments than it expected
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/cast_fn_ptr1.rs:LL:CC
= note: inside `main` at $DIR/abi_mismatch_too_many_args.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
11 changes: 11 additions & 0 deletions tests/fail/function_pointers/abi_mismatch_vector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![feature(portable_simd)]
use std::simd;

fn main() {
fn f(_: simd::u32x8) {}

// These two vector types have the same size but are still not compatible.
let g = unsafe { std::mem::transmute::<fn(simd::u32x8), fn(simd::u64x4)>(f) };

g(Default::default()) //~ ERROR: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
}
15 changes: 15 additions & 0 deletions tests/fail/function_pointers/abi_mismatch_vector.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
--> $DIR/abi_mismatch_vector.rs:LL:CC
|
LL | g(Default::default())
| ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to previous error

78 changes: 70 additions & 8 deletions tests/pass/function_calls/abi_compat.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,91 @@
#![feature(portable_simd)]
use std::mem;
use std::num;
use std::simd;

fn test_abi_compat<T, U>(t: T, u: U) {
#[derive(Copy, Clone)]
struct Zst;

fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
fn id<T>(x: T) -> T {
x
}
extern "C" fn id_c<T>(x: T) -> T {
x
}

// This checks ABI compatibility both for arguments and return values,
// in both directions.
let f: fn(T) -> T = id;
let f: fn(U) -> U = unsafe { std::mem::transmute(f) };
drop(f(u));

let _val = f(u);
let f: fn(U) -> U = id;
let f: fn(T) -> T = unsafe { std::mem::transmute(f) };
drop(f(t));
let _val = f(t);

// And then we do the same for `extern "C"`.
let f: extern "C" fn(T) -> T = id_c;
let f: extern "C" fn(U) -> U = unsafe { std::mem::transmute(f) };
let _val = f(u);
let f: extern "C" fn(U) -> U = id_c;
let f: extern "C" fn(T) -> T = unsafe { std::mem::transmute(f) };
let _val = f(t);
}

/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
fn test_abi_newtype<T: Copy>(t: T) {
#[repr(transparent)]
#[derive(Copy, Clone)]
struct Wrapper1<T>(T);
#[repr(transparent)]
#[derive(Copy, Clone)]
struct Wrapper2<T>(T, ());
#[repr(transparent)]
#[derive(Copy, Clone)]
struct Wrapper2a<T>((), T);
#[repr(transparent)]
#[derive(Copy, Clone)]
struct Wrapper3<T>(Zst, T, [u8; 0]);

test_abi_compat(t, Wrapper1(t));
test_abi_compat(t, Wrapper2(t, ()));
test_abi_compat(t, Wrapper2a((), t));
test_abi_compat(t, Wrapper3(Zst, t, []));
test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)`
}

fn main() {
// Here we check:
// - unsigned vs signed integer is allowed
// - u32/i32 vs char is allowed
// - u32 vs NonZeroU32/Option<NonZeroU32> is allowed
// - reference vs raw pointer is allowed
// - references to things of the same size and alignment are allowed
// These are very basic tests that should work on all ABIs. However it is not clear that any of
// these would be stably guaranteed. Code that relies on this is equivalent to code that relies
// on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields
// of a struct (even with `repr(C)`) will not always be accepted by Miri.
test_abi_compat(0u32, 0i32);
test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1));
test_abi_compat(0u32, 'x');
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
test_abi_compat(0u32, mem::MaybeUninit::new(0u32));
test_abi_compat(0i32, 'x');
test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
test_abi_compat(0u32, 0i32);
// Note that `bool` and `u8` are *not* compatible!
test_abi_compat(&0u32, &0u32 as *const u32);
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
// Note that `bool` and `u8` are *not* compatible, at least on x86-64!
// One of them has `arg_ext: Zext`, the other does not.

// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
// with the wrapped field.
test_abi_newtype(());
// FIXME: this still fails! test_abi_newtype(Zst);
test_abi_newtype(0u32);
test_abi_newtype(0f32);
test_abi_newtype((0u32, 1u32, 2u32));
// FIXME: skipping the array tests on mips64 due to https://github.com/rust-lang/rust/issues/115404
if !cfg!(target_arch = "mips64") {
test_abi_newtype([0u32, 1u32, 2u32]);
test_abi_newtype([0i32; 0]);
}
}