Skip to content

Commit d780907

Browse files
committed
Auto merge of #3059 - rust-lang:rustup-2023-09-12, r=RalfJung
Automatic sync from rustc
2 parents 0e6fa25 + 02e399c commit d780907

18 files changed

+166
-36
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
aeddd2ddfd35bb385dd36476fab326f40d57a131
1+
366dab13f711df90a6891411458544199d159cbc

src/bin/miri.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
5959

6060
fn after_analysis<'tcx>(
6161
&mut self,
62-
handler: &EarlyErrorHandler,
6362
_: &rustc_interface::interface::Compiler,
6463
queries: &'tcx rustc_interface::Queries<'tcx>,
6564
) -> Compilation {
@@ -68,7 +67,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
6867
tcx.sess.fatal("miri cannot be run on programs that fail compilation");
6968
}
7069

71-
init_late_loggers(handler, tcx);
70+
let handler = EarlyErrorHandler::new(tcx.sess.opts.error_format);
71+
init_late_loggers(&handler, tcx);
7272
if !tcx.crate_types().contains(&CrateType::Executable) {
7373
tcx.sess.fatal("miri only makes sense on bin crates");
7474
}

src/diagnostics.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ pub fn report_error<'tcx, 'mir>(
199199
e: InterpErrorInfo<'tcx>,
200200
) -> Option<(i64, bool)> {
201201
use InterpError::*;
202+
use UndefinedBehaviorInfo::*;
202203

203204
let mut msg = vec![];
204205

@@ -271,7 +272,7 @@ pub fn report_error<'tcx, 'mir>(
271272
(title, helps)
272273
} else {
273274
let title = match e.kind() {
274-
UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(validation_err))
275+
UndefinedBehavior(ValidationError(validation_err))
275276
if matches!(
276277
validation_err.kind,
277278
ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer
@@ -299,7 +300,7 @@ pub fn report_error<'tcx, 'mir>(
299300
let helps = match e.kind() {
300301
Unsupported(_) =>
301302
vec![(None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"))],
302-
UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. })
303+
UndefinedBehavior(AlignmentCheckFailed { .. })
303304
if ecx.machine.check_alignment == AlignmentCheck::Symbolic
304305
=>
305306
vec![
@@ -311,13 +312,20 @@ pub fn report_error<'tcx, 'mir>(
311312
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
312313
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
313314
];
314-
if let UndefinedBehaviorInfo::PointerUseAfterFree(alloc_id, _) | UndefinedBehaviorInfo::PointerOutOfBounds { alloc_id, .. } = info {
315-
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
316-
helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
315+
match info {
316+
PointerUseAfterFree(alloc_id, _) | PointerOutOfBounds { alloc_id, .. } => {
317+
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
318+
helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
319+
}
320+
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
321+
helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
322+
}
317323
}
318-
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
319-
helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
324+
AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => {
325+
helps.push((None, format!("this means these two types are not *guaranteed* to be ABI-compatible across all targets")));
326+
helps.push((None, format!("if you think this code should be accepted anyway, please report an issue")));
320327
}
328+
_ => {},
321329
}
322330
helps
323331
}
@@ -339,7 +347,7 @@ pub fn report_error<'tcx, 'mir>(
339347
// We want to dump the allocation if this is `InvalidUninitBytes`. Since `format_error` consumes `e`, we compute the outut early.
340348
let mut extra = String::new();
341349
match e.kind() {
342-
UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
350+
UndefinedBehavior(InvalidUninitBytes(Some((alloc_id, access)))) => {
343351
writeln!(
344352
extra,
345353
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",

tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | g(Default::default())
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
10+
= help: if you think this code should be accepted anyway, please report an issue
911
= note: BACKTRACE:
1012
= note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
1113

tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | g(42)
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
10+
= help: if you think this code should be accepted anyway, please report an issue
911
= note: BACKTRACE:
1012
= note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC
1113

tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | g(&42 as *const i32)
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
10+
= help: if you think this code should be accepted anyway, please report an issue
911
= note: BACKTRACE:
1012
= note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC
1113

tests/fail/function_pointers/abi_mismatch_return_type.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | g()
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
10+
= help: if you think this code should be accepted anyway, please report an issue
911
= note: BACKTRACE:
1012
= note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC
1113

tests/fail/function_pointers/abi_mismatch_simple.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | g(42)
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
10+
= help: if you think this code should be accepted anyway, please report an issue
911
= note: BACKTRACE:
1012
= note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC
1113

tests/fail/function_pointers/abi_mismatch_vector.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | g(Default::default())
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
10+
= help: if you think this code should be accepted anyway, please report an issue
911
= note: BACKTRACE:
1012
= note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC
1113

tests/fail/validity/cast_fn_ptr1.stderr renamed to tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: constructing invalid value: encountered a null reference
2-
--> $DIR/cast_fn_ptr1.rs:LL:CC
2+
--> $DIR/cast_fn_ptr_invalid_callee_arg.rs:LL:CC
33
|
44
LL | g(0usize as *const i32)
55
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr1.rs:LL:CC
10+
= note: inside `main` at $DIR/cast_fn_ptr_invalid_callee_arg.rs:LL:CC
1111

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![allow(internal_features)]
2+
#![feature(core_intrinsics, custom_mir)]
3+
4+
use std::intrinsics::mir::*;
5+
use std::num::NonZeroU32;
6+
use std::ptr;
7+
8+
// This function supposedly returns a NonZeroU32, but actually returns something invalid in a way that
9+
// never materializes a bad NonZeroU32 value: we take a pointer to the return place and cast the pointer
10+
// type. That way we never get an "invalid value constructed" error inside the function, it can
11+
// only possibly be detected when the return value is passed to the caller.
12+
#[custom_mir(dialect = "runtime", phase = "optimized")]
13+
fn f() -> NonZeroU32 {
14+
mir! {
15+
{
16+
let tmp = ptr::addr_of_mut!(RET);
17+
let ptr = tmp as *mut u32;
18+
*ptr = 0;
19+
Return()
20+
}
21+
}
22+
}
23+
24+
fn main() {
25+
let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZeroU32) };
26+
// There's a NonZeroU32-to-u32 transmute happening here
27+
f(); //~ERROR: expected something greater or equal to 1
28+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
2+
--> $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
3+
|
4+
LL | f();
5+
| ^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to previous error
15+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#![allow(internal_features)]
2+
#![feature(core_intrinsics, custom_mir)]
3+
4+
use std::intrinsics::mir::*;
5+
use std::num::NonZeroU32;
6+
use std::ptr;
7+
8+
fn f(c: u32) {
9+
println!("{c}");
10+
}
11+
12+
// Call that function in a bad way, with an invalid NonZeroU32, but without
13+
// ever materializing this as a NonZeroU32 value outside the call itself.
14+
#[custom_mir(dialect = "runtime", phase = "optimized")]
15+
fn call(f: fn(NonZeroU32)) {
16+
mir! {
17+
let _res: ();
18+
{
19+
let c = 0;
20+
let tmp = ptr::addr_of!(c);
21+
let ptr = tmp as *const NonZeroU32;
22+
// The call site now is a NonZeroU32-to-u32 transmute.
23+
Call(_res = f(*ptr), retblock) //~ERROR: expected something greater or equal to 1
24+
}
25+
retblock = {
26+
Return()
27+
}
28+
}
29+
}
30+
31+
fn main() {
32+
let f: fn(NonZeroU32) = unsafe { std::mem::transmute(f as fn(u32)) };
33+
call(f);
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
2+
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
3+
|
4+
LL | Call(_res = f(*ptr), retblock)
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `call` at $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
13+
|
14+
LL | call(f);
15+
| ^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to previous error
20+

tests/fail/validity/cast_fn_ptr2.stderr renamed to tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: constructing invalid value: encountered a null reference
2-
--> $DIR/cast_fn_ptr2.rs:LL:CC
2+
--> $DIR/cast_fn_ptr_invalid_caller_ret.rs:LL:CC
33
|
44
LL | let _x = g();
55
| ^^^ constructing invalid value: encountered a null reference
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr2.rs:LL:CC
10+
= note: inside `main` at $DIR/cast_fn_ptr_invalid_caller_ret.rs:LL:CC
1111

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

tests/pass/function_calls/abi_compat.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
use std::mem;
22
use std::num;
3+
use std::ptr;
34

45
#[derive(Copy, Clone, Default)]
56
struct Zst;
67

7-
fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
8+
#[repr(transparent)]
9+
#[derive(Copy, Clone)]
10+
struct Wrapper<T>(T);
11+
12+
fn id<T>(x: T) -> T {
13+
x
14+
}
15+
16+
fn test_abi_compat<T: Clone, U: Clone>(t: T, u: U) {
817
fn id<T>(x: T) -> T {
918
x
1019
}
@@ -16,10 +25,10 @@ fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
1625
// in both directions.
1726
let f: fn(T) -> T = id;
1827
let f: fn(U) -> U = unsafe { std::mem::transmute(f) };
19-
let _val = f(u);
28+
let _val = f(u.clone());
2029
let f: fn(U) -> U = id;
2130
let f: fn(T) -> T = unsafe { std::mem::transmute(f) };
22-
let _val = f(t);
31+
let _val = f(t.clone());
2332

2433
// And then we do the same for `extern "C"`.
2534
let f: extern "C" fn(T) -> T = id_c;
@@ -32,9 +41,6 @@ fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
3241

3342
/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
3443
fn test_abi_newtype<T: Copy + Default>() {
35-
#[repr(transparent)]
36-
#[derive(Copy, Clone)]
37-
struct Wrapper1<T>(T);
3844
#[repr(transparent)]
3945
#[derive(Copy, Clone)]
4046
struct Wrapper2<T>(T, ());
@@ -46,31 +52,38 @@ fn test_abi_newtype<T: Copy + Default>() {
4652
struct Wrapper3<T>(Zst, T, [u8; 0]);
4753

4854
let t = T::default();
49-
test_abi_compat(t, Wrapper1(t));
55+
test_abi_compat(t, Wrapper(t));
5056
test_abi_compat(t, Wrapper2(t, ()));
5157
test_abi_compat(t, Wrapper2a((), t));
5258
test_abi_compat(t, Wrapper3(Zst, t, []));
5359
test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)`
5460
}
5561

5662
fn main() {
57-
// Here we check:
58-
// - u32 vs char is allowed
59-
// - u32 vs NonZeroU32/Option<NonZeroU32> is allowed
60-
// - reference vs raw pointer is allowed
61-
// - references to things of the same size and alignment are allowed
62-
// These are very basic tests that should work on all ABIs. However it is not clear that any of
63-
// these would be stably guaranteed. Code that relies on this is equivalent to code that relies
64-
// on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields
65-
// of a struct (even with `repr(C)`) will not always be accepted by Miri.
66-
// Note that `bool` and `u8` are *not* compatible, at least on x86-64!
67-
// One of them has `arg_ext: Zext`, the other does not.
68-
// Similarly, `i32` and `u32` are not compatible on s390x due to different `arg_ext`.
69-
test_abi_compat(0u32, 'x');
63+
// Here we check some of the guaranteed ABI compatibilities.
64+
// Different integer types of the same size and sign.
65+
if cfg!(target_pointer_width = "32") {
66+
test_abi_compat(0usize, 0u32);
67+
test_abi_compat(0isize, 0i32);
68+
} else {
69+
test_abi_compat(0usize, 0u64);
70+
test_abi_compat(0isize, 0i64);
71+
}
7072
test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
71-
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
73+
// Reference/pointer types with the same pointee.
7274
test_abi_compat(&0u32, &0u32 as *const u32);
75+
test_abi_compat(&mut 0u32 as *mut u32, Box::new(0u32));
76+
test_abi_compat(&(), ptr::NonNull::<()>::dangling());
77+
// Reference/pointer types with different but sized pointees.
7378
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
79+
// `fn` types
80+
test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
81+
// Guaranteed null-pointer-optimizations.
82+
test_abi_compat(&0u32 as *const u32, Some(&0u32));
83+
test_abi_compat(main as fn(), Some(main as fn()));
84+
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
85+
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
86+
test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1).unwrap())));
7487

7588
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
7689
// with the wrapped field.

0 commit comments

Comments
 (0)