From 12ae11813d8f8c573f4dca24494fc88480bda9c7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Aug 2023 14:45:03 +0200 Subject: [PATCH 01/14] fix some bad regex capture group references in test normalization --- .../tests/fail/function_calls/exported_symbol_bad_unwind2.rs | 4 ++-- .../miri/tests/fail/intrinsics/uninit_uninhabited_type.rs | 4 ++-- src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs | 4 ++-- src/tools/miri/tests/fail/panic/double_panic.rs | 4 ++-- src/tools/miri/tests/fail/terminate-terminator.rs | 4 ++-- src/tools/miri/tests/fail/unwind-action-terminate.rs | 4 ++-- src/tools/miri/tests/pass/panic/nested_panic_caught.rs | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs index 10bd5eb7211..e6aff19b02d 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs @@ -1,8 +1,8 @@ //@revisions: extern_block definition both //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" //@[definition,both]error-in-other-file: aborted execution #![feature(rustc_attrs, c_unwind)] diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs index b8fa32c986f..6e0e0ca9f53 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs @@ -1,7 +1,7 @@ //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution #![feature(never_type)] diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs index 70ae60593a1..0e8d3d08c12 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs @@ -1,7 +1,7 @@ //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution #[allow(deprecated, invalid_value)] diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs index 4627e9f1c8e..ddc75521eca 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.rs +++ b/src/tools/miri/tests/fail/panic/double_panic.rs @@ -1,7 +1,7 @@ //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution struct Foo; diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs index 5373b5f70c0..7c672828030 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.rs +++ b/src/tools/miri/tests/fail/terminate-terminator.rs @@ -1,8 +1,8 @@ //@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000 //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution // Enable MIR inlining to ensure that `TerminatorKind::UnwindTerminate` is generated // instead of just `UnwindAction::Terminate`. diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs index 77844844483..86406872c59 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.rs +++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs @@ -1,8 +1,8 @@ //@error-in-other-file: aborted execution //@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" #![feature(c_unwind)] extern "C" fn panic_abort() { diff --git a/src/tools/miri/tests/pass/panic/nested_panic_caught.rs b/src/tools/miri/tests/pass/panic/nested_panic_caught.rs index 884813150ad..bbfcc25a0c6 100644 --- a/src/tools/miri/tests/pass/panic/nested_panic_caught.rs +++ b/src/tools/miri/tests/pass/panic/nested_panic_caught.rs @@ -1,6 +1,6 @@ //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1" -//@normalize-stderr-test: "\n at [^\n]+" -> "$1" +//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +//@normalize-stderr-test: "\n +at [^\n]+" -> "" // Checks that nested panics work correctly. From 20479074f4a68b855310ad79022499d7c7e08ade Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 26 Aug 2023 05:25:22 +0000 Subject: [PATCH 02/14] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d96e7040aaf..f0eb71c0017 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c40cfcf0494ff7506e753e750adb00eeea839f9c +9334ec93541fd6963a3bfa2d2d09e3e33ac93131 From ec91a2361ba0de6aa90f92fe620d49ef84b177ef Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sat, 26 Aug 2023 05:34:03 +0000 Subject: [PATCH 03/14] fmt --- src/tools/miri/src/machine.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 98f82ec9a0f..9d01a04bf4a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -975,7 +975,10 @@ fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResu ecx.start_panic_nounwind(msg) } - fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: mir::UnwindTerminateReason) -> InterpResult<'tcx> { + fn unwind_terminate( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + reason: mir::UnwindTerminateReason, + ) -> InterpResult<'tcx> { // Call the lang item. let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap(); let panic = ty::Instance::mono(ecx.tcx.tcx, panic); @@ -1410,17 +1413,14 @@ fn after_local_allocated( ecx: &mut InterpCx<'mir, 'tcx, Self>, frame: usize, local: mir::Local, - mplace: &MPlaceTy<'tcx, Provenance> + mplace: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else { panic!("after_local_allocated should only be called on fresh allocations"); }; let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local]; let span = local_decl.source_info.span; - ecx.machine - .allocation_spans - .borrow_mut() - .insert(alloc_id, (span, None)); + ecx.machine.allocation_spans.borrow_mut().insert(alloc_id, (span, None)); Ok(()) } } From 0966799b63ed0ed2ebdcddd386d4645de6732601 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Aug 2023 12:12:45 +0200 Subject: [PATCH 04/14] tests/catch_panic: make output easier to interpret --- .../miri/tests/pass/panic/catch_panic.rs | 16 ++++++++------- .../miri/tests/pass/panic/catch_panic.stderr | 20 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/tools/miri/tests/pass/panic/catch_panic.rs b/src/tools/miri/tests/pass/panic/catch_panic.rs index 1b00f7cea30..e4a7f8e3481 100644 --- a/src/tools/miri/tests/pass/panic/catch_panic.rs +++ b/src/tools/miri/tests/pass/panic/catch_panic.rs @@ -1,5 +1,5 @@ // We test the `align_offset` panic below, make sure we test the interpreter impl and not the "real" one. -//@compile-flags: -Zmiri-symbolic-alignment-check -Zmiri-permissive-provenance +//@compile-flags: -Zmiri-symbolic-alignment-check #![feature(never_type)] #![allow(unconditional_panic, non_fmt_panics)] @@ -48,14 +48,16 @@ fn main() { })); // Std panics - test(None, |_old_val| std::panic!("Hello from panic: std")); - test(None, |old_val| std::panic::panic_any(format!("Hello from panic: {:?}", old_val))); - test(None, |old_val| std::panic!("Hello from panic: {:?}", old_val)); + test(None, |_old_val| std::panic!("Hello from std::panic")); + test(None, |old_val| std::panic!("Hello from std::panic: {:?}", old_val)); + test(None, |old_val| { + std::panic::panic_any(format!("Hello from std::panic_any: {:?}", old_val)) + }); test(None, |_old_val| std::panic::panic_any(1337)); // Core panics - test(None, |_old_val| core::panic!("Hello from panic: core")); - test(None, |old_val| core::panic!("Hello from panic: {:?}", old_val)); + test(None, |_old_val| core::panic!("Hello from core::panic")); + test(None, |old_val| core::panic!("Hello from core::panic: {:?}", old_val)); // Built-in panics; also make sure the message is right. test(Some("index out of bounds: the len is 3 but the index is 4"), |_old_val| { @@ -68,7 +70,7 @@ fn main() { }); test(Some("align_offset: align is not a power-of-two"), |_old_val| { - let _ = (0usize as *const u8).align_offset(3); + let _ = std::ptr::null::().align_offset(3); loop {} }); diff --git a/src/tools/miri/tests/pass/panic/catch_panic.stderr b/src/tools/miri/tests/pass/panic/catch_panic.stderr index aa005590db3..cbcd626e39f 100644 --- a/src/tools/miri/tests/pass/panic/catch_panic.stderr +++ b/src/tools/miri/tests/pass/panic/catch_panic.stderr @@ -1,22 +1,22 @@ thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: -Hello from panic: std +Hello from std::panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -Caught panic message (&str): Hello from panic: std +Caught panic message (&str): Hello from std::panic thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: -Hello from panic: 1 -Caught panic message (String): Hello from panic: 1 +Hello from std::panic: 1 +Caught panic message (String): Hello from std::panic: 1 thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: -Hello from panic: 2 -Caught panic message (String): Hello from panic: 2 +Hello from std::panic_any: 2 +Caught panic message (String): Hello from std::panic_any: 2 thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: Box Failed to get caught panic message. thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: -Hello from panic: core -Caught panic message (&str): Hello from panic: core +Hello from core::panic +Caught panic message (&str): Hello from core::panic thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: -Hello from panic: 5 -Caught panic message (String): Hello from panic: 5 +Hello from core::panic: 5 +Caught panic message (String): Hello from core::panic: 5 thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: index out of bounds: the len is 3 but the index is 4 Caught panic message (String): index out of bounds: the len is 3 but the index is 4 From ce6f3048953b2373704d3075b2fec9e7aeaab586 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Aug 2023 13:44:42 +0200 Subject: [PATCH 05/14] move basic track_caller test into their own fn --- .../miri/tests/pass/track-caller-attribute.rs | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/tools/miri/tests/pass/track-caller-attribute.rs b/src/tools/miri/tests/pass/track-caller-attribute.rs index 6694764a234..d0473f746cd 100644 --- a/src/tools/miri/tests/pass/track-caller-attribute.rs +++ b/src/tools/miri/tests/pass/track-caller-attribute.rs @@ -21,6 +21,44 @@ macro_rules! caller_location_from_macro { }; } +fn test_basic() { + let location = Location::caller(); + let expected_line = line!() - 1; + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line); + assert_eq!(location.column(), 20); + + let tracked = tracked(); + let expected_line = line!() - 1; + assert_eq!(tracked.file(), file!()); + assert_eq!(tracked.line(), expected_line); + assert_eq!(tracked.column(), 19); + + let nested = nested_intrinsic(); + assert_eq!(nested.file(), file!()); + assert_eq!(nested.line(), 11); + assert_eq!(nested.column(), 5); + + let contained = nested_tracked(); + assert_eq!(contained.file(), file!()); + assert_eq!(contained.line(), 15); + assert_eq!(contained.column(), 5); + + // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, + // i.e. point to where the macro was invoked, instead of the macro itself. + let inmacro = caller_location_from_macro!(); + let expected_line = line!() - 1; + assert_eq!(inmacro.file(), file!()); + assert_eq!(inmacro.line(), expected_line); + assert_eq!(inmacro.column(), 19); + + let intrinsic = core::intrinsics::caller_location(); + let expected_line = line!() - 1; + assert_eq!(intrinsic.file(), file!()); + assert_eq!(intrinsic.line(), expected_line); + assert_eq!(intrinsic.column(), 21); +} + fn test_fn_ptr() { fn pass_to_ptr_call(f: fn(T), x: T) { f(x); @@ -88,42 +126,7 @@ fn foo(&self) -> &'static Location<'static> { } fn main() { - let location = Location::caller(); - let expected_line = line!() - 1; - assert_eq!(location.file(), file!()); - assert_eq!(location.line(), expected_line); - assert_eq!(location.column(), 20); - - let tracked = tracked(); - let expected_line = line!() - 1; - assert_eq!(tracked.file(), file!()); - assert_eq!(tracked.line(), expected_line); - assert_eq!(tracked.column(), 19); - - let nested = nested_intrinsic(); - assert_eq!(nested.file(), file!()); - assert_eq!(nested.line(), 11); - assert_eq!(nested.column(), 5); - - let contained = nested_tracked(); - assert_eq!(contained.file(), file!()); - assert_eq!(contained.line(), 15); - assert_eq!(contained.column(), 5); - - // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, - // i.e. point to where the macro was invoked, instead of the macro itself. - let inmacro = caller_location_from_macro!(); - let expected_line = line!() - 1; - assert_eq!(inmacro.file(), file!()); - assert_eq!(inmacro.line(), expected_line); - assert_eq!(inmacro.column(), 19); - - let intrinsic = core::intrinsics::caller_location(); - let expected_line = line!() - 1; - assert_eq!(intrinsic.file(), file!()); - assert_eq!(intrinsic.line(), expected_line); - assert_eq!(intrinsic.column(), 21); - + test_basic(); test_fn_ptr(); test_trait_obj(); test_trait_obj2(); From e24fdbe5ab80e36c97d92495ee9d3f2cee05946e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Aug 2023 13:48:09 +0200 Subject: [PATCH 06/14] add tests for track_caller in closures and generators --- .../miri/tests/pass/track-caller-attribute.rs | 153 +++++++++++++++++- 1 file changed, 148 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/tests/pass/track-caller-attribute.rs b/src/tools/miri/tests/pass/track-caller-attribute.rs index d0473f746cd..1b0226e61b5 100644 --- a/src/tools/miri/tests/pass/track-caller-attribute.rs +++ b/src/tools/miri/tests/pass/track-caller-attribute.rs @@ -1,17 +1,25 @@ #![feature(core_intrinsics)] +#![feature(stmt_expr_attributes)] +#![feature(closure_track_caller)] +#![feature(generator_trait)] +#![feature(generators)] +use std::ops::{Generator, GeneratorState}; use std::panic::Location; +use std::pin::Pin; + +type Loc = &'static Location<'static>; #[track_caller] -fn tracked() -> &'static Location<'static> { +fn tracked() -> Loc { Location::caller() // most importantly, we never get line 7 } -fn nested_intrinsic() -> &'static Location<'static> { +fn nested_intrinsic() -> Loc { Location::caller() } -fn nested_tracked() -> &'static Location<'static> { +fn nested_tracked() -> Loc { tracked() } @@ -36,12 +44,12 @@ fn test_basic() { let nested = nested_intrinsic(); assert_eq!(nested.file(), file!()); - assert_eq!(nested.line(), 11); + assert_eq!(nested.line(), 19); assert_eq!(nested.column(), 5); let contained = nested_tracked(); assert_eq!(contained.file(), file!()); - assert_eq!(contained.line(), 15); + assert_eq!(contained.line(), 23); assert_eq!(contained.column(), 5); // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, @@ -125,9 +133,144 @@ fn foo(&self) -> &'static Location<'static> { assert_eq!(loc.line(), expected_line); } +fn test_closure() { + #[track_caller] + fn mono_invoke_fn (&'static str, bool, Loc)>( + val: &F, + ) -> (&'static str, bool, Loc) { + val("from_mono", false) + } + + #[track_caller] + fn mono_invoke_fn_once (&'static str, bool, Loc)>( + val: F, + ) -> (&'static str, bool, Loc) { + val("from_mono", false) + } + + #[track_caller] + fn dyn_invoke_fn_mut( + val: &mut dyn FnMut(&'static str, bool) -> (&'static str, bool, Loc), + ) -> (&'static str, bool, Loc) { + val("from_dyn", false) + } + + #[track_caller] + fn dyn_invoke_fn_once( + val: Box (&'static str, bool, Loc)>, + ) -> (&'static str, bool, Loc) { + val("from_dyn", false) + } + + let mut track_closure = #[track_caller] + |first: &'static str, second: bool| (first, second, Location::caller()); + let (first_arg, first_bool, first_loc) = track_closure("first_arg", true); + let first_line = line!() - 1; + assert_eq!(first_arg, "first_arg"); + assert_eq!(first_bool, true); + assert_eq!(first_loc.file(), file!()); + assert_eq!(first_loc.line(), first_line); + assert_eq!(first_loc.column(), 46); + + let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_mut(&mut track_closure); + assert_eq!(dyn_arg, "from_dyn"); + assert_eq!(dyn_bool, false); + // `FnMut::call_mut` does not have `#[track_caller]`, + // so this will not match + assert_ne!(dyn_loc.file(), file!()); + + let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_once(Box::new(track_closure)); + assert_eq!(dyn_arg, "from_dyn"); + assert_eq!(dyn_bool, false); + // `FnOnce::call_once` does not have `#[track_caller]` + // so this will not match + assert_ne!(dyn_loc.file(), file!()); + + let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn(&track_closure); + let mono_line = line!() - 1; + assert_eq!(mono_arg, "from_mono"); + assert_eq!(mono_bool, false); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 43); + + let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn_once(track_closure); + let mono_line = line!() - 1; + assert_eq!(mono_arg, "from_mono"); + assert_eq!(mono_bool, false); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 43); + + let non_tracked_caller = || Location::caller(); + let non_tracked_line = line!() - 1; // This is the line of the closure, not its caller + let non_tracked_loc = non_tracked_caller(); + assert_eq!(non_tracked_loc.file(), file!()); + assert_eq!(non_tracked_loc.line(), non_tracked_line); + assert_eq!(non_tracked_loc.column(), 33); +} + +fn test_generator() { + #[track_caller] + fn mono_generator>( + val: Pin<&mut F>, + ) -> (&'static str, String, Loc) { + match val.resume("Mono".to_string()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!(), + } + } + + #[track_caller] + fn dyn_generator( + val: Pin<&mut dyn Generator>, + ) -> (&'static str, String, Loc) { + match val.resume("Dyn".to_string()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!(), + } + } + + #[rustfmt::skip] + let generator = #[track_caller] |arg: String| { + yield ("first", arg.clone(), Location::caller()); + yield ("second", arg.clone(), Location::caller()); + }; + + let mut pinned = Box::pin(generator); + let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut()); + assert_eq!(dyn_ret, "first"); + assert_eq!(dyn_arg, "Dyn".to_string()); + // The `Generator` trait does not have `#[track_caller]` on `resume`, so + // this will not match. + assert_ne!(dyn_loc.file(), file!()); + + let (mono_ret, mono_arg, mono_loc) = mono_generator(pinned.as_mut()); + let mono_line = line!() - 1; + assert_eq!(mono_ret, "second"); + // The generator ignores the argument to the second `resume` call + assert_eq!(mono_arg, "Dyn".to_string()); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 42); + + #[rustfmt::skip] + let non_tracked_generator = || { yield Location::caller(); }; + let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller + let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!(), + }; + assert_eq!(non_tracked_loc.file(), file!()); + assert_eq!(non_tracked_loc.line(), non_tracked_line); + assert_eq!(non_tracked_loc.column(), 44); +} + fn main() { test_basic(); test_fn_ptr(); test_trait_obj(); test_trait_obj2(); + test_closure(); + test_generator(); } From ca7acd48e6f9878b023d1d3b39e46c04bef14a7e Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Tue, 29 Aug 2023 05:36:35 +0000 Subject: [PATCH 07/14] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index f0eb71c0017..da0d794273b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -9334ec93541fd6963a3bfa2d2d09e3e33ac93131 +f3284dc3ad9254236d296daa1285dd273b492b01 From fb3565a848af21af18c26156f0acae9115257e46 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Tue, 29 Aug 2023 05:45:20 +0000 Subject: [PATCH 08/14] fmt --- src/tools/miri/tests/pass/function_calls/abi_compat.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index 67b87b46bd9..e586700b0eb 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -1,15 +1,17 @@ -use std::num; use std::mem; +use std::num; fn test_abi_compat(t: T, u: U) { - fn id(x: T) -> T { x } - + fn id(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 f: fn(U) -> U = id; let f: fn(T) -> T = unsafe { std::mem::transmute(f) }; drop(f(t)); From 4b915b8a86df64e6758b6cc329d83d5fe635f21d Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Thu, 31 Aug 2023 05:34:07 +0000 Subject: [PATCH 09/14] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index da0d794273b..88a4ddfba6b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f3284dc3ad9254236d296daa1285dd273b492b01 +008c21c9779fd1e3632d9fe908b8afc0c421b26c From f57b41519dc3bd863650114c344e8e7db7a1cc2d Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Thu, 31 Aug 2023 05:42:55 +0000 Subject: [PATCH 10/14] fmt --- src/tools/miri/src/diagnostics.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 75c6911bcbe..298c5367522 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -272,26 +272,24 @@ pub fn report_error<'tcx, 'mir>( } else { let title = match e.kind() { UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(validation_err)) - if matches!(validation_err.kind, ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer) => + if matches!( + validation_err.kind, + ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer + ) => { ecx.handle_ice(); // print interpreter backtrace bug!("This validation error should be impossible in Miri: {}", ecx.format_error(e)); } - UndefinedBehavior(_) => - "Undefined Behavior", - ResourceExhaustion(_) => - "resource exhaustion", + UndefinedBehavior(_) => "Undefined Behavior", + ResourceExhaustion(_) => "resource exhaustion", Unsupported( // We list only the ones that can actually happen. - UnsupportedOpInfo::Unsupported(_) | UnsupportedOpInfo::UnsizedLocal - ) => - "unsupported operation", + UnsupportedOpInfo::Unsupported(_) | UnsupportedOpInfo::UnsizedLocal, + ) => "unsupported operation", InvalidProgram( // We list only the ones that can actually happen. - InvalidProgramInfo::AlreadyReported(_) | - InvalidProgramInfo::Layout(..) - ) => - "post-monomorphization error", + InvalidProgramInfo::AlreadyReported(_) | InvalidProgramInfo::Layout(..), + ) => "post-monomorphization error", _ => { ecx.handle_ice(); // print interpreter backtrace bug!("This error should be impossible in Miri: {}", ecx.format_error(e)); @@ -346,7 +344,8 @@ pub fn report_error<'tcx, 'mir>( extra, "Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:", range = access.bad, - ).unwrap(); + ) + .unwrap(); writeln!(extra, "{:?}", ecx.dump_alloc(*alloc_id)).unwrap(); } _ => {} From d86be8d32e4bfc2db39817464f6932831272b4f9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 09:21:12 +0200 Subject: [PATCH 11/14] make sure we test all tier 1 targets: i686-pc-windows-gnu was missing --- src/tools/miri/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 3146ef41a3b..a3fc68e6758 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -107,7 +107,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests - MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests + MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings From 4ea6a4bfe399ac12f00ef10b0c3f674fb5db8581 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 11:32:11 +0200 Subject: [PATCH 12/14] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 88a4ddfba6b..f173cc37e85 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -008c21c9779fd1e3632d9fe908b8afc0c421b26c +dca2d1ff00bf96d244b1bb9a2117a92ec50ac71d From 9db09c571fa4cc73278796afc2669533348e27c4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 11:34:43 +0200 Subject: [PATCH 13/14] fmt --- src/tools/miri/tests/pass/function_calls/abi_compat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index 4821a50916f..30ab2d05889 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -1,6 +1,6 @@ #![feature(portable_simd)] -use std::num; use std::mem; +use std::num; use std::simd; fn test_abi_compat(t: T, u: U) { From c2b0ca75aad47edcc403738c49387284ce55f5bf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 11:35:31 +0200 Subject: [PATCH 14/14] more ABI compat tests --- .../tests/pass/function_calls/abi_compat.rs | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index 30ab2d05889..dc1e1f0ba8d 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -3,53 +3,89 @@ use std::num; use std::simd; -fn test_abi_compat(t: T, u: U) { +#[derive(Copy, Clone)] +struct Zst; + +fn test_abi_compat(t: T, u: U) { fn id(x: T) -> T { x } + extern "C" fn id_c(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: T) { #[repr(transparent)] + #[derive(Copy, Clone)] struct Wrapper1(T); #[repr(transparent)] + #[derive(Copy, Clone)] struct Wrapper2(T, ()); #[repr(transparent)] + #[derive(Copy, Clone)] struct Wrapper2a((), T); #[repr(transparent)] - struct Wrapper3(T, [u8; 0]); + #[derive(Copy, Clone)] + struct Wrapper3(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(t, [])); + test_abi_compat(t, Wrapper3(Zst, t, [])); + test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)` } fn main() { - test_abi_compat(0u32, 'x'); - test_abi_compat(&0u32, &([true; 4], [0u32; 0])); - test_abi_compat(0u32, mem::MaybeUninit::new(0u32)); - test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap()); - test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap())); + // Here we check: + // - unsigned vs signed integer is allowed + // - u32/i32 vs char is allowed + // - u32 vs NonZeroU32/Option 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(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, &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)); - test_abi_newtype([0u32, 1u32, 2u32]); - test_abi_newtype([0i32; 0]); + // 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]); + } }