diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index d104ff0891d34..2daf591bd65be 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -516,7 +516,8 @@ E0793: include_str!("./error_codes/E0793.md"), E0794: include_str!("./error_codes/E0794.md"), } -// Undocumented removed error codes. Note that many removed error codes are documented. +// Undocumented removed error codes. Note that many removed error codes are kept in the list above +// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example). // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard // E0019, // merged into E0015 diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 0207923ed1892..a548de814c53d 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -408,9 +408,10 @@ pub mod __alloc_error_handler { if unsafe { __rust_alloc_error_handler_should_panic != 0 } { panic!("memory allocation of {size} bytes failed") } else { - core::panicking::panic_nounwind_fmt(format_args!( - "memory allocation of {size} bytes failed" - )) + core::panicking::panic_nounwind_fmt( + format_args!("memory allocation of {size} bytes failed"), + /* force_no_backtrace */ false, + ) } } } diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index c7f04f11ef618..c77e9675a6ac5 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -28,6 +28,7 @@ pub struct PanicInfo<'a> { message: Option<&'a fmt::Arguments<'a>>, location: &'a Location<'a>, can_unwind: bool, + force_no_backtrace: bool, } impl<'a> PanicInfo<'a> { @@ -42,9 +43,10 @@ impl<'a> PanicInfo<'a> { message: Option<&'a fmt::Arguments<'a>>, location: &'a Location<'a>, can_unwind: bool, + force_no_backtrace: bool, ) -> Self { struct NoPayload; - PanicInfo { location, message, payload: &NoPayload, can_unwind } + PanicInfo { location, message, payload: &NoPayload, can_unwind, force_no_backtrace } } #[unstable( @@ -141,6 +143,17 @@ impl<'a> PanicInfo<'a> { pub fn can_unwind(&self) -> bool { self.can_unwind } + + #[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" + )] + #[doc(hidden)] + #[inline] + pub fn force_no_backtrace(&self) -> bool { + self.force_no_backtrace + } } #[stable(feature = "panic_hook_display", since = "1.26.0")] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index ab6aa0df42828..281f8c1e1663c 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -61,7 +61,12 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { fn panic_impl(pi: &PanicInfo<'_>) -> !; } - let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true); + let pi = PanicInfo::internal_constructor( + Some(&fmt), + Location::caller(), + /* can_unwind */ true, + /* force_no_backtrace */ false, + ); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. unsafe { panic_impl(&pi) } @@ -77,7 +82,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, // which causes a "panic in a function that cannot unwind". #[rustc_nounwind] -pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! { +pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } @@ -90,7 +95,12 @@ pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! { } // PanicInfo with the `can_unwind` flag set to false forces an abort. - let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false); + let pi = PanicInfo::internal_constructor( + Some(&fmt), + Location::caller(), + /* can_unwind */ false, + force_no_backtrace, + ); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. unsafe { panic_impl(&pi) } @@ -123,7 +133,15 @@ pub const fn panic(expr: &'static str) -> ! { #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] pub fn panic_nounwind(expr: &'static str) -> ! { - panic_nounwind_fmt(fmt::Arguments::new_const(&[expr])); + panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false); +} + +/// Like `panic_nounwind`, but also inhibits showing a backtrace. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[rustc_nounwind] +pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! { + panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true); } #[inline] @@ -172,9 +190,12 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { super::intrinsics::abort() } - panic_nounwind_fmt(format_args!( - "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}" - )) + panic_nounwind_fmt( + format_args!( + "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}" + ), + /* force_no_backtrace */ false, + ) } /// Panic because we cannot unwind out of a function. @@ -205,7 +226,7 @@ fn panic_cannot_unwind() -> ! { #[rustc_nounwind] fn panic_in_cleanup() -> ! { // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. - panic_nounwind("panic in a destructor during cleanup") + panic_nounwind_nobacktrace("panic in a destructor during cleanup") } /// This function is used instead of panic_fmt in const eval. diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b08d5782ab6f4..1e8d28979e6be 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -656,10 +656,10 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_div(self, rhs: u32) -> Option { if rhs != 0 { - let secs = self.secs / (rhs as u64); - let carry = self.secs - secs * (rhs as u64); - let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); - let nanos = self.nanos.0 / rhs + (extra_nanos as u32); + let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64)); + let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs); + nanos += + ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32; debug_assert!(nanos < NANOS_PER_SEC); Some(Duration::new(secs, nanos)) } else { diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index 872611937cc08..bd6e63edbb9e5 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -170,6 +170,7 @@ fn saturating_mul() { fn div() { assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); + assert_eq!(Duration::new(1, 1) / 7, Duration::new(0, 142_857_143)); assert_eq!(Duration::new(99, 999_999_000) / 100, Duration::new(0, 999_999_990)); } diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 3d4302e665c20..6a6af9efd78ed 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -662,7 +662,7 @@ fn test_send_vectored_fds_unix_stream() { } } -#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] +#[cfg(any(target_os = "android", target_os = "linux"))] #[test] #[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets fn test_send_vectored_with_ancillary_to_unix_datagram() { diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 6ff7b19f293d3..b20e5464e6e01 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -246,7 +246,9 @@ fn default_hook(info: &PanicInfo<'_>) { pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path::Path>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. - let backtrace = if panic_count::get_count() >= 2 { + let backtrace = if info.force_no_backtrace() { + None + } else if panic_count::get_count() >= 2 { BacktraceStyle::full() } else { crate::panic::get_backtrace_style() @@ -294,7 +296,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path } } } - // If backtraces aren't supported, do nothing. + // If backtraces aren't supported or are forced-off, do nothing. None => {} } }; @@ -615,14 +617,23 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message().unwrap(); // The current implementation always returns Some crate::sys_common::backtrace::__rust_end_short_backtrace(move || { + // FIXME: can we just pass `info` along rather than taking it apart here, only to have + // `rust_panic_with_hook` construct a new `PanicInfo`? if let Some(msg) = msg.as_str() { - rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind()); + rust_panic_with_hook( + &mut StrPanicPayload(msg), + info.message(), + loc, + info.can_unwind(), + info.force_no_backtrace(), + ); } else { rust_panic_with_hook( &mut PanicPayload::new(msg), info.message(), loc, info.can_unwind(), + info.force_no_backtrace(), ); } }) @@ -647,7 +658,13 @@ pub const fn begin_panic(msg: M) -> ! { let loc = Location::caller(); return crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, true) + rust_panic_with_hook( + &mut PanicPayload::new(msg), + None, + loc, + /* can_unwind */ true, + /* force_no_backtrace */ false, + ) }); struct PanicPayload { @@ -693,6 +710,7 @@ fn rust_panic_with_hook( message: Option<&fmt::Arguments<'_>>, location: &Location<'_>, can_unwind: bool, + force_no_backtrace: bool, ) -> ! { let must_abort = panic_count::increase(true); @@ -707,14 +725,20 @@ fn rust_panic_with_hook( panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating // a `Backtrace` will allocate, which we must to avoid here. - let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind); + let panicinfo = PanicInfo::internal_constructor( + message, + location, + can_unwind, + force_no_backtrace, + ); rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n"); } } crate::sys::abort_internal(); } - let mut info = PanicInfo::internal_constructor(message, location, can_unwind); + let mut info = + PanicInfo::internal_constructor(message, location, can_unwind, force_no_backtrace); let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner); match *hook { // Some platforms (like wasm) know that printing to stderr won't ever actually diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 00e2857a13759..c638cc61856fa 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -176,6 +176,14 @@ pub struct Instant(time::Instant); /// The size of a `SystemTime` struct may vary depending on the target operating /// system. /// +/// A `SystemTime` does not count leap seconds. +/// `SystemTime::now()`'s behaviour around a leap second +/// is the same as the operating system's wall clock. +/// The precise behaviour near a leap second +/// (e.g. whether the clock appears to run slow or fast, or stop, or jump) +/// depends on platform and configuration, +/// so should not be relied on. +/// /// Example: /// /// ```no_run @@ -461,6 +469,9 @@ impl fmt::Debug for Instant { impl SystemTime { /// An anchor in time which can be used to create new `SystemTime` instances or /// learn about where in time a `SystemTime` lies. + // + // NOTE! this documentation is duplicated, here and in std::time::UNIX_EPOCH. + // The two copies are not quite identical, because of the difference in naming. /// /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with /// respect to the system clock. Using `duration_since` on an existing @@ -468,6 +479,11 @@ impl SystemTime { /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a /// `SystemTime` instance to represent another fixed point in time. /// + /// `duration_since(UNIX_EPOCH).unwrap().as_secs()` returns + /// the number of non-leap seconds since the start of 1970 UTC. + /// This is a POSIX `time_t` (as a `u64`), + /// and is the same time representation as used in many Internet protocols. + /// /// # Examples /// /// ```no_run @@ -617,6 +633,9 @@ impl fmt::Debug for SystemTime { /// An anchor in time which can be used to create new `SystemTime` instances or /// learn about where in time a `SystemTime` lies. +// +// NOTE! this documentation is duplicated, here and in SystemTime::UNIX_EPOCH. +// The two copies are not quite identical, because of the difference in naming. /// /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with /// respect to the system clock. Using `duration_since` on an existing @@ -624,6 +643,11 @@ impl fmt::Debug for SystemTime { /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a /// [`SystemTime`] instance to represent another fixed point in time. /// +/// `duration_since(UNIX_EPOCH).unwrap().as_secs()` returns +/// the number of non-leap seconds since the start of 1970 UTC. +/// This is a POSIX `time_t` (as a `u64`), +/// and is the same time representation as used in many Internet protocols. +/// /// # Examples /// /// ```no_run diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 32c604f9f3e10..e9ef509e6a21d 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -400,7 +400,12 @@ constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a function call (ignoring the `!`), so format it using the rules for function calls. -### Special case macros +The style guide defines specific formatting for particular macros in the +language or standard library. The style guide does not define formatting for +any third-party macros, even if similar to those in the language or standard +library. + +### Format string macros For macros which take a format string, if all other arguments are *small*, format the arguments before the format string on a single line if they fit, and diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index 9efba031250be..a39522c8a61ae 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -6,7 +6,6 @@ second stack backtrace: thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a destructor during cleanup -stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC @@ -19,7 +18,7 @@ LL | ABORT(); = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC - = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC + = note: inside `core::panicking::panic_nounwind_nobacktrace` at RUSTLIB/core/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC note: inside `main` --> $DIR/double_panic.rs:LL:CC diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 417ace58c325d..3e67bac499b0b 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -354,7 +354,12 @@ fn check_error_codes_used( for code in error_codes { if !found_codes.contains(code) && !no_longer_emitted.contains(code) { - errors.push(format!("Error code `{code}` exists, but is not emitted by the compiler!")) + errors.push(format!( + "Error code `{code}` exists, but is not emitted by the compiler!\n\ + Please mark the code as no longer emitted by adding the following note to the top of the `EXXXX.md` file:\n\ + `#### Note: this error code is no longer emitted by the compiler`\n\ + Also, do not forget to mark doctests that no longer apply as `ignore (error is no longer emitted)`." + )); } if found_codes.contains(code) && no_longer_emitted.contains(code) { diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace.rs index 95783945529a5..84be333beffe3 100644 --- a/tests/ui/backtrace.rs +++ b/tests/ui/backtrace.rs @@ -94,7 +94,7 @@ fn runtest(me: &str) { #[cfg(not(panic = "abort"))] { // Make sure a stack trace is printed - let p = template(me).arg("double-fail").spawn().unwrap(); + let p = template(me).arg("double-fail").env("RUST_BACKTRACE","0").spawn().unwrap(); let out = p.wait_with_output().unwrap(); assert!(!out.status.success()); let s = str::from_utf8(&out.stderr).unwrap(); @@ -106,18 +106,18 @@ fn runtest(me: &str) { contains_verbose_expected(s, "double"), "bad output3: {}", s ); + // Make sure it's only one stack trace. + assert_eq!(s.split("stack backtrace").count(), 2); // Make sure a stack trace isn't printed too many times - // - // Currently it is printed 3 times ("once", "twice" and "panic in a destructor during - // cleanup") but in the future the last one may be removed. + // even with RUST_BACKTRACE=1. It should be printed twice. let p = template(me).arg("double-fail") .env("RUST_BACKTRACE", "1").spawn().unwrap(); let out = p.wait_with_output().unwrap(); assert!(!out.status.success()); let s = str::from_utf8(&out.stderr).unwrap(); let mut i = 0; - for _ in 0..3 { + for _ in 0..2 { i += s[i + 10..].find("stack backtrace").unwrap() + 10; } assert!(s[i + 10..].find("stack backtrace").is_none(), diff --git a/tests/ui/panics/panic-in-cleanup.rs b/tests/ui/panics/panic-in-cleanup.rs index a1c797268d107..84880f1881cac 100644 --- a/tests/ui/panics/panic-in-cleanup.rs +++ b/tests/ui/panics/panic-in-cleanup.rs @@ -4,6 +4,7 @@ // error-pattern: panic in a destructor during cleanup // normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" // normalize-stderr-test: "\n +at [^\n]+" -> "" +// normalize-stderr-test: "(core/src/panicking\.rs):[0-9]+:[0-9]+" -> "$1:$$LINE:$$COL" // needs-unwind // ignore-emscripten "RuntimeError" junk in output // ignore-msvc SEH doesn't do panic-during-cleanup the same way as everyone else diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr index 923bac69c50ef..e7def11b0e948 100644 --- a/tests/ui/panics/panic-in-cleanup.run.stderr +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -1,10 +1,9 @@ -thread 'main' panicked at $DIR/panic-in-cleanup.rs:21:5: +thread 'main' panicked at $DIR/panic-in-cleanup.rs:22:5: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at $DIR/panic-in-cleanup.rs:15:9: +thread 'main' panicked at $DIR/panic-in-cleanup.rs:16:9: BOOM stack backtrace: -thread 'main' panicked at library/core/src/panicking.rs:126:5: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: panic in a destructor during cleanup -stack backtrace: thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs index da2b24945bed1..d9f1fcee85546 100644 --- a/tests/ui/panics/panic-in-ffi.rs +++ b/tests/ui/panics/panic-in-ffi.rs @@ -4,6 +4,7 @@ // error-pattern: panic in a function that cannot unwind // normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" // normalize-stderr-test: "\n +at [^\n]+" -> "" +// normalize-stderr-test: "(core/src/panicking\.rs):[0-9]+:[0-9]+" -> "$1:$$LINE:$$COL" // needs-unwind // ignore-emscripten "RuntimeError" junk in output #![feature(c_unwind)] diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr index 3422f5ccc4d3c..a92a66c57fd7d 100644 --- a/tests/ui/panics/panic-in-ffi.run.stderr +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -1,7 +1,7 @@ -thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5: +thread 'main' panicked at $DIR/panic-in-ffi.rs:13:5: Test note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at library/core/src/panicking.rs:126:5: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting.