diff options
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/macros/mod.rs | 3 | ||||
| -rw-r--r-- | library/core/src/macros/panic.md | 30 | ||||
| -rw-r--r-- | library/core/src/marker.rs | 10 | ||||
| -rw-r--r-- | library/core/src/net/ip_addr.rs | 8 | ||||
| -rw-r--r-- | library/core/src/num/f32.rs | 20 | ||||
| -rw-r--r-- | library/core/src/num/f64.rs | 20 | ||||
| -rw-r--r-- | library/core/src/ops/drop.rs | 10 | ||||
| -rw-r--r-- | library/core/src/panic/panic_info.rs | 15 | ||||
| -rw-r--r-- | library/core/src/panicking.rs | 37 | ||||
| -rw-r--r-- | library/core/src/time.rs | 8 |
10 files changed, 127 insertions, 34 deletions
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 14cc523b0c1..46628bcea00 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -849,7 +849,8 @@ pub(crate) mod builtin { /// assert_eq!(display, debug); /// ``` /// - /// For more information, see the documentation in [`std::fmt`]. + /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html) + /// for details of the macro argument syntax, and further information. /// /// [`Display`]: crate::fmt::Display /// [`Debug`]: crate::fmt::Debug diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 8b549e187ba..60100c2655a 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -8,8 +8,8 @@ tests. `panic!` is closely tied with the `unwrap` method of both [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set to [`None`] or [`Err`] variants. -When using `panic!()` you can specify a string payload, that is built using -the [`format!`] syntax. That payload is used when injecting the panic into +When using `panic!()` you can specify a string payload that is built using +[formatting syntax]. That payload is used when injecting the panic into the calling Rust thread, causing the thread to panic entirely. The behavior of the default `std` hook, i.e. the code that runs directly @@ -18,6 +18,7 @@ after the panic is invoked, is to print the message payload to call. You can override the panic hook using [`std::panic::set_hook()`]. Inside the hook a panic can be accessed as a `&dyn Any + Send`, which contains either a `&str` or `String` for regular `panic!()` invocations. +(Whether a particular invocation contains the payload at type `&str` or `String` is unspecified and can change.) To panic with a value of another other type, [`panic_any`] can be used. See also the macro [`compile_error!`], for raising errors during compilation. @@ -55,7 +56,7 @@ For more detailed information about error handling check out the [book] or the [`panic_any`]: ../std/panic/fn.panic_any.html [`Box`]: ../std/boxed/struct.Box.html [`Any`]: crate::any::Any -[`format!`]: ../std/macro.format.html +[`format!` syntax]: ../std/fmt/index.html [book]: ../book/ch09-00-error-handling.html [`std::result`]: ../std/result/index.html @@ -64,6 +65,29 @@ For more detailed information about error handling check out the [book] or the If the main thread panics it will terminate all your threads and end your program with code `101`. +# Editions + +Behavior of the panic macros changed over editions. + +## 2021 and later + +In Rust 2021 and later, `panic!` always requires a format string and +the applicable format arguments, and is the same in `core` and `std`. +Use [`std::panic::panic_any(x)`](../std/panic/fn.panic_any.html) to +panic with an arbitrary payload. + +## 2018 and 2015 + +In Rust Editions prior to 2021, `std::panic!(x)` with a single +argument directly uses that argument as a payload. +This is true even if the argument is a string literal. +For example, `panic!("problem: {reason}")` panics with a +payload of literally `"problem: {reason}"` (a `&'static str`). + +`core::panic!(x)` with a single argument requires that `x` be `&str`, +but otherwise behaves like `std::panic!`. In particular, the string +need not be a literal, and is not interpreted as a format string. + # Examples ```should_panic diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index aec287226a0..5ec751e5168 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -76,11 +76,8 @@ macro marker_impls { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Send")] #[rustc_on_unimplemented( - on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"), message = "`{Self}` cannot be sent between threads safely", - label = "`{Self}` cannot be sent between threads safely", - note = "consider using `std::sync::Arc<{Self}>`; for more information visit \ - <https://doc.rust-lang.org/book/ch16-03-shared-state.html>" + label = "`{Self}` cannot be sent between threads safely" )] pub unsafe auto trait Send { // empty. @@ -631,11 +628,8 @@ impl<T: ?Sized> Copy for &T {} any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"), note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead", ), - on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"), message = "`{Self}` cannot be shared between threads safely", - label = "`{Self}` cannot be shared between threads safely", - note = "consider using `std::sync::Arc<{Self}>`; for more information visit \ - <https://doc.rust-lang.org/book/ch16-03-shared-state.html>" + label = "`{Self}` cannot be shared between threads safely" )] pub unsafe auto trait Sync { // FIXME(estebank): once support to add notes in `rustc_on_unimplemented` diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 56460c75eba..6a36dfec098 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1856,13 +1856,7 @@ impl fmt::Display for Ipv6Addr { if f.precision().is_none() && f.width().is_none() { let segments = self.segments(); - // Special case for :: and ::1; otherwise they get written with the - // IPv4 formatter - if self.is_unspecified() { - f.write_str("::") - } else if self.is_loopback() { - f.write_str("::1") - } else if let Some(ipv4) = self.to_ipv4_mapped() { + if let Some(ipv4) = self.to_ipv4_mapped() { write!(f, "::ffff:{}", ipv4) } else { #[derive(Copy, Clone, Default)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index d050d21c8c5..3144db19707 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -277,6 +277,14 @@ pub mod consts { #[stable(feature = "tau_constant", since = "1.47.0")] pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; + /// The golden ratio (φ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f32 = 1.618033988749894848204586834365638118_f32; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f32 = 0.577215664901532860606512090082402431_f32; + /// π/2 #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32; @@ -301,6 +309,10 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32; + /// 1/sqrt(π) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32; + /// 2/π #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32; @@ -317,6 +329,14 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; + /// sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f32 = 1.732050807568877293527446341505872367_f32; + + /// 1/sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f32 = 2.71828182845904523536028747135266250_f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index d9a738191f7..20833defc41 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -277,6 +277,14 @@ pub mod consts { #[stable(feature = "tau_constant", since = "1.47.0")] pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; + /// The golden ratio (φ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f64 = 1.618033988749894848204586834365638118_f64; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f64 = 0.577215664901532860606512090082402431_f64; + /// π/2 #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64; @@ -301,6 +309,10 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64; + /// 1/sqrt(π) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64; + /// 2/π #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64; @@ -317,6 +329,14 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; + /// sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f64 = 1.732050807568877293527446341505872367_f64; + + /// 1/sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 9ebf426be95..21c23dabfc2 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -217,8 +217,13 @@ pub trait Drop { /// /// # Panics /// - /// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`] - /// in a `drop` implementation will likely abort. + /// Implementations should generally avoid [`panic!`]ing, because `drop()` may itself be called + /// during unwinding due to a panic, and if the `drop()` panics in that situation (a “double + /// panic”), this will likely abort the program. It is possible to check [`panicking()`] first, + /// which may be desirable for a `Drop` implementation that is reporting a bug of the kind + /// “you didn't finish using this before it was dropped”; but most types should simply clean up + /// their owned allocations or other resources and return normally from `drop()`, regardless of + /// what state they are in. /// /// Note that even if this panics, the value is considered to be dropped; /// you must not cause `drop` to be called again. This is normally automatically @@ -227,6 +232,7 @@ pub trait Drop { /// /// [E0040]: ../../error_codes/E0040.html /// [`panic!`]: crate::panic! + /// [`panicking()`]: ../../std/thread/fn.panicking.html /// [`mem::drop`]: drop /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index c7f04f11ef6..c77e9675a6a 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 ab6aa0df428..281f8c1e166 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 b08d5782ab6..1e8d28979e6 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<Duration> { 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 { |
