diff options
Diffstat (limited to 'library/core/src')
29 files changed, 947 insertions, 243 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index bb75ec74c81..835ee57ce23 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -184,18 +184,12 @@ pub struct TryFromSliceError(()); impl fmt::Display for TryFromSliceError { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[allow(deprecated)] - self.description().fmt(f) + "could not convert slice to array".fmt(f) } } #[stable(feature = "try_from", since = "1.34.0")] -impl Error for TryFromSliceError { - #[allow(deprecated)] - fn description(&self) -> &str { - "could not convert slice to array" - } -} +impl Error for TryFromSliceError {} #[stable(feature = "try_from_slice_error", since = "1.36.0")] #[rustc_const_unstable(feature = "const_try", issue = "74935")] diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 23061cb663b..cf5a91bf8dd 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -193,21 +193,16 @@ enum CharErrorKind { } #[stable(feature = "char_from_str", since = "1.20.0")] -impl Error for ParseCharError { - #[allow(deprecated)] - fn description(&self) -> &str { - match self.kind { - CharErrorKind::EmptyString => "cannot parse char from empty string", - CharErrorKind::TooManyChars => "too many characters in string", - } - } -} +impl Error for ParseCharError {} #[stable(feature = "char_from_str", since = "1.20.0")] impl fmt::Display for ParseCharError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[allow(deprecated)] - self.description().fmt(f) + match self.kind { + CharErrorKind::EmptyString => "cannot parse char from empty string", + CharErrorKind::TooManyChars => "too many characters in string", + } + .fmt(f) } } diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs index 23319fbe5dd..d7c5f45ae4e 100644 --- a/library/core/src/char/decode.rs +++ b/library/core/src/char/decode.rs @@ -126,9 +126,4 @@ impl fmt::Display for DecodeUtf16Error { } #[stable(feature = "decode_utf16", since = "1.9.0")] -impl Error for DecodeUtf16Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "unpaired surrogate found" - } -} +impl Error for DecodeUtf16Error {} diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 7ee0962721f..985e669c92d 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1872,28 +1872,33 @@ pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) { // SAFETY: The caller must guarantee that the buffer pointed to by `dst` // is at least `len` bytes long. unsafe { - match len { - 1 => { - *dst = code as u8; - } - 2 => { - *dst = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - *dst.add(1) = (code & 0x3F) as u8 | TAG_CONT; - } - 3 => { - *dst = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *dst.add(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *dst.add(2) = (code & 0x3F) as u8 | TAG_CONT; - } - 4 => { - *dst = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - *dst.add(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *dst.add(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *dst.add(3) = (code & 0x3F) as u8 | TAG_CONT; - } - // SAFETY: `char` always takes between 1 and 4 bytes to encode in UTF-8. - _ => crate::hint::unreachable_unchecked(), + if len == 1 { + *dst = code as u8; + return; + } + + let last1 = (code >> 0 & 0x3F) as u8 | TAG_CONT; + let last2 = (code >> 6 & 0x3F) as u8 | TAG_CONT; + let last3 = (code >> 12 & 0x3F) as u8 | TAG_CONT; + let last4 = (code >> 18 & 0x3F) as u8 | TAG_FOUR_B; + + if len == 2 { + *dst = last2 | TAG_TWO_B; + *dst.add(1) = last1; + return; } + + if len == 3 { + *dst = last3 | TAG_THREE_B; + *dst.add(1) = last2; + *dst.add(2) = last1; + return; + } + + *dst = last4; + *dst.add(1) = last3; + *dst.add(2) = last2; + *dst.add(3) = last1; } } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 0c3034c3d4c..a0a7b7928d1 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -958,11 +958,7 @@ impl fmt::Display for Infallible { } #[stable(feature = "str_parse_error2", since = "1.8.0")] -impl Error for Infallible { - fn description(&self) -> &str { - match *self {} - } -} +impl Error for Infallible {} #[stable(feature = "convert_infallible", since = "1.34.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 88e633c9eef..92b3c83d1bf 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -1042,11 +1042,6 @@ impl<'a> crate::iter::FusedIterator for Source<'a> {} #[stable(feature = "error_by_ref", since = "1.51.0")] impl<'a, T: Error + ?Sized> Error for &'a T { - #[allow(deprecated, deprecated_in_future)] - fn description(&self) -> &str { - Error::description(&**self) - } - #[allow(deprecated)] fn cause(&self) -> Option<&dyn Error> { Error::cause(&**self) @@ -1062,36 +1057,16 @@ impl<'a, T: Error + ?Sized> Error for &'a T { } #[stable(feature = "fmt_error", since = "1.11.0")] -impl Error for crate::fmt::Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "an error occurred when formatting an argument" - } -} +impl Error for crate::fmt::Error {} #[stable(feature = "try_borrow", since = "1.13.0")] -impl Error for crate::cell::BorrowError { - #[allow(deprecated)] - fn description(&self) -> &str { - "already mutably borrowed" - } -} +impl Error for crate::cell::BorrowError {} #[stable(feature = "try_borrow", since = "1.13.0")] -impl Error for crate::cell::BorrowMutError { - #[allow(deprecated)] - fn description(&self) -> &str { - "already borrowed" - } -} +impl Error for crate::cell::BorrowMutError {} #[stable(feature = "try_from", since = "1.34.0")] -impl Error for crate::char::CharTryFromError { - #[allow(deprecated)] - fn description(&self) -> &str { - "converted integer out of range for `char`" - } -} +impl Error for crate::char::CharTryFromError {} #[stable(feature = "duration_checked_float", since = "1.66.0")] impl Error for crate::time::TryFromFloatSecsError {} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 8ac29e5b076..b6de8925308 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -359,7 +359,7 @@ impl FormattingOptions { /// always be printed. /// - `-`: Currently not used #[unstable(feature = "formatting_options", issue = "118117")] - pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self { + pub const fn sign(&mut self, sign: Option<Sign>) -> &mut Self { let sign = match sign { None => 0, Some(Sign::Plus) => flags::SIGN_PLUS_FLAG, @@ -372,7 +372,7 @@ impl FormattingOptions { /// /// This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware #[unstable(feature = "formatting_options", issue = "118117")] - pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self { + pub const fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self { if sign_aware_zero_pad { self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG; } else { @@ -389,7 +389,7 @@ impl FormattingOptions { /// - [`Octal`] - precedes the argument with a `0b` /// - [`Binary`] - precedes the argument with a `0o` #[unstable(feature = "formatting_options", issue = "118117")] - pub fn alternate(&mut self, alternate: bool) -> &mut Self { + pub const fn alternate(&mut self, alternate: bool) -> &mut Self { if alternate { self.flags |= flags::ALTERNATE_FLAG; } else { @@ -404,7 +404,7 @@ impl FormattingOptions { /// being formatted is smaller than width some extra characters will be /// printed around it. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn fill(&mut self, fill: char) -> &mut Self { + pub const fn fill(&mut self, fill: char) -> &mut Self { self.flags = self.flags & (u32::MAX << 21) | fill as u32; self } @@ -413,7 +413,7 @@ impl FormattingOptions { /// The alignment specifies how the value being formatted should be /// positioned if it is smaller than the width of the formatter. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn align(&mut self, align: Option<Alignment>) -> &mut Self { + pub const fn align(&mut self, align: Option<Alignment>) -> &mut Self { let align: u32 = match align { Some(Alignment::Left) => flags::ALIGN_LEFT, Some(Alignment::Right) => flags::ALIGN_RIGHT, @@ -430,7 +430,7 @@ impl FormattingOptions { /// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`] /// will be used to take up the required space. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn width(&mut self, width: Option<u16>) -> &mut Self { + pub const fn width(&mut self, width: Option<u16>) -> &mut Self { if let Some(width) = width { self.flags |= flags::WIDTH_FLAG; self.width = width; @@ -450,7 +450,7 @@ impl FormattingOptions { /// - For floating-point types, this indicates how many digits after the /// decimal point should be printed. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn precision(&mut self, precision: Option<u16>) -> &mut Self { + pub const fn precision(&mut self, precision: Option<u16>) -> &mut Self { if let Some(precision) = precision { self.flags |= flags::PRECISION_FLAG; self.precision = precision; @@ -463,7 +463,7 @@ impl FormattingOptions { /// Specifies whether the [`Debug`] trait should use lower-/upper-case /// hexadecimal or normal integers #[unstable(feature = "formatting_options", issue = "118117")] - pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self { + pub const fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self { let debug_as_hex = match debug_as_hex { None => 0, Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG, @@ -537,7 +537,7 @@ impl FormattingOptions { /// /// You may alternatively use [`Formatter::new()`]. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> { + pub const fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> { Formatter { options: self, buf: write } } } @@ -578,13 +578,13 @@ impl<'a> Formatter<'a> { /// /// You may alternatively use [`FormattingOptions::create_formatter()`]. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self { + pub const fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self { Formatter { options, buf: write } } /// Creates a new formatter based on this one with given [`FormattingOptions`]. #[unstable(feature = "formatting_options", issue = "118117")] - pub fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> { + pub const fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> { Formatter { options, buf: self.buf } } } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index c72eeb9a9c9..535c5a8e77b 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -267,39 +267,29 @@ pub const unsafe fn assert_unchecked(cond: bool) { #[inline(always)] #[stable(feature = "renamed_spin_loop", since = "1.49.0")] pub fn spin_loop() { - #[cfg(target_arch = "x86")] - { - // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. - unsafe { crate::arch::x86::_mm_pause() }; - } - - #[cfg(target_arch = "x86_64")] - { - // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. - unsafe { crate::arch::x86_64::_mm_pause() }; - } - - #[cfg(target_arch = "riscv32")] - { - crate::arch::riscv32::pause(); - } - - #[cfg(target_arch = "riscv64")] - { - crate::arch::riscv64::pause(); - } - - #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] - { - // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. - unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }; - } - - #[cfg(all(target_arch = "arm", target_feature = "v6"))] - { - // SAFETY: the `cfg` attr ensures that we only execute this on arm targets - // with support for the v6 feature. - unsafe { crate::arch::arm::__yield() }; + crate::cfg_select! { + target_arch = "x86" => { + // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. + unsafe { crate::arch::x86::_mm_pause() } + } + target_arch = "x86_64" => { + // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. + unsafe { crate::arch::x86_64::_mm_pause() } + } + target_arch = "riscv32" => crate::arch::riscv32::pause(), + target_arch = "riscv64" => crate::arch::riscv64::pause(), + any(target_arch = "aarch64", target_arch = "arm64ec") => { + // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. + unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) } + } + all(target_arch = "arm", target_feature = "v6") => { + // SAFETY: the `cfg` attr ensures that we only execute this on arm targets + // with support for the v6 feature. + unsafe { crate::arch::arm::__yield() } + } + target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(), + target_arch = "loongarch64" => crate::arch::loongarch64::ibar::<0>(), + _ => { /* do nothing */ } } } diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 12e2b8b393a..73122369b41 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -1,5 +1,5 @@ use crate::iter; -use crate::num::Wrapping; +use crate::num::{Saturating, Wrapping}; /// Trait to represent types that can be created by summing up an iterator. /// @@ -98,6 +98,61 @@ macro_rules! integer_sum_product { ); } +macro_rules! saturating_integer_sum_product { + (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($( + #[$attr] + #[doc = $doc] + impl Sum for $a { + fn sum<I: Iterator<Item=Self>>(iter: I) -> Self { + iter.fold( + $zero, + |a, b| a + b, + ) + } + } + + #[$attr] + #[doc = $doc] + impl Product for $a { + fn product<I: Iterator<Item=Self>>(iter: I) -> Self { + iter.fold( + $one, + |a, b| a * b, + ) + } + } + + #[$attr] + #[doc = $doc] + impl<'a> Sum<&'a $a> for $a { + fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self { + iter.fold( + $zero, + |a, b| a + b, + ) + } + } + + #[$attr] + #[doc = $doc] + impl<'a> Product<&'a $a> for $a { + fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self { + iter.fold( + $one, + |a, b| a * b, + ) + } + } + )*); + ($($a:ty)*) => ( + saturating_integer_sum_product!(@impls Saturating(0), Saturating(1), + "The short-circuiting behavior of this implementation is unspecified. If you care about \ + short-circuiting, use [`Iterator::fold`] directly.", + #[stable(feature = "saturating_iter_arith", since = "CURRENT_RUSTC_VERSION")], + $(Saturating<$a>)*); + ); +} + macro_rules! float_sum_product { ($($a:ident)*) => ($( #[stable(feature = "iter_arith_traits", since = "1.12.0")] @@ -147,6 +202,7 @@ macro_rules! float_sum_product { } integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } +saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } #[stable(feature = "iter_arith_traits_result", since = "1.16.0")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f69d6a98592..82506379cac 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -363,6 +363,8 @@ pub mod slice; pub mod str; pub mod time; +pub mod wtf8; + pub mod unicode; /* Async */ diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 8ad58599c68..73aad27afef 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1049,7 +1049,7 @@ marker_impls! { /// A marker for types that can be dropped. /// -/// This should be used for `~const` bounds, +/// This should be used for `[const]` bounds, /// as non-const bounds will always hold for every type. #[unstable(feature = "const_destruct", issue = "133214")] #[rustc_const_unstable(feature = "const_destruct", issue = "133214")] diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs index 73230f6ee5b..3aab24a90d8 100644 --- a/library/core/src/net/parser.rs +++ b/library/core/src/net/parser.rs @@ -497,16 +497,7 @@ pub struct AddrParseError(AddrKind); #[stable(feature = "addr_parse_error_error", since = "1.4.0")] impl fmt::Display for AddrParseError { - #[allow(deprecated, deprecated_in_future)] - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.write_str(self.description()) - } -} - -#[stable(feature = "addr_parse_error_error", since = "1.4.0")] -impl Error for AddrParseError { - #[allow(deprecated)] - fn description(&self) -> &str { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { AddrKind::Ip => "invalid IP address syntax", AddrKind::Ipv4 => "invalid IPv4 address syntax", @@ -515,5 +506,9 @@ impl Error for AddrParseError { AddrKind::SocketV4 => "invalid IPv4 socket address syntax", AddrKind::SocketV6 => "invalid IPv6 socket address syntax", } + .fmt(f) } } + +#[stable(feature = "addr_parse_error_error", since = "1.4.0")] +impl Error for AddrParseError {} diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index 3118a6e5ca6..dd4eccd24de 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -219,21 +219,16 @@ enum FloatErrorKind { } #[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseFloatError { - #[allow(deprecated)] - fn description(&self) -> &str { - match self.kind { - FloatErrorKind::Empty => "cannot parse float from empty string", - FloatErrorKind::Invalid => "invalid float literal", - } - } -} +impl Error for ParseFloatError {} #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for ParseFloatError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[allow(deprecated)] - self.description().fmt(f) + match self.kind { + FloatErrorKind::Empty => "cannot parse float from empty string", + FloatErrorKind::Invalid => "invalid float literal", + } + .fmt(f) } } diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index cfedd465cab..faa52329827 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -11,19 +11,13 @@ pub struct TryFromIntError(pub(crate) ()); #[stable(feature = "try_from", since = "1.34.0")] impl fmt::Display for TryFromIntError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - #[allow(deprecated)] - self.description().fmt(fmt) + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "out of range integral type conversion attempted".fmt(f) } } #[stable(feature = "try_from", since = "1.34.0")] -impl Error for TryFromIntError { - #[allow(deprecated)] - fn description(&self) -> &str { - "out of range integral type conversion attempted" - } -} +impl Error for TryFromIntError {} #[stable(feature = "try_from", since = "1.34.0")] #[rustc_const_unstable(feature = "const_try", issue = "74935")] @@ -128,15 +122,6 @@ impl ParseIntError { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for ParseIntError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[allow(deprecated)] - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseIntError { - #[allow(deprecated)] - fn description(&self) -> &str { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", IntErrorKind::InvalidDigit => "invalid digit found in string", @@ -144,5 +129,9 @@ impl Error for ParseIntError { IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", } + .fmt(f) } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for ParseIntError {} diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 69e6c100e76..4282b1af9f2 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -630,6 +630,13 @@ impl f128 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f128)] /// # // FIXME(f16_f128): remove when `eqtf2` is available @@ -645,13 +652,22 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_degrees(self) -> Self { - // Use a literal for better precision. - const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128; + // The division here is correctly rounded with respect to the true value of 180/π. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f128. + const PIS_IN_180: f128 = 180.0 / consts::PI; self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f128)] /// # // FIXME(f16_f128): remove when `eqtf2` is available @@ -668,7 +684,8 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_radians(self) -> f128 { - // Use a literal for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const RADS_PER_DEG: f128 = 0.0174532925199432957692369076848861271344287188854172545609719_f128; self * RADS_PER_DEG diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index b66cef03d20..23a8661c14b 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -625,6 +625,13 @@ impl f16 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f16)] /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms @@ -640,13 +647,21 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_degrees(self) -> Self { - // Use a literal for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16; self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f16)] /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms @@ -663,7 +678,8 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_radians(self) -> f16 { - // Use a literal for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16; self * RADS_PER_DEG } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index f8344da79ad..da08bfc5950 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -839,6 +839,13 @@ impl f32 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = std::f32::consts::PI; /// @@ -852,13 +859,21 @@ impl f32 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_degrees(self) -> f32 { - // Use a constant for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = 180.0f32; /// @@ -872,6 +887,9 @@ impl f32 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_radians(self) -> f32 { + // The division here is correctly rounded with respect to the true value of π/180. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f32. const RADS_PER_DEG: f32 = consts::PI / 180.0; self * RADS_PER_DEG } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 93da63c896e..dc0977cb147 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -856,6 +856,13 @@ impl f64 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = std::f64::consts::PI; /// @@ -869,14 +876,22 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_degrees(self) -> f64 { - // The division here is correctly rounded with respect to the true - // value of 180/π. (This differs from f32, where a constant must be - // used to ensure a correctly rounded result.) - self * (180.0f64 / consts::PI) + // The division here is correctly rounded with respect to the true value of 180/π. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f64. + const PIS_IN_180: f64 = 180.0 / consts::PI; + self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = 180.0_f64; /// @@ -890,6 +905,9 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_radians(self) -> f64 { + // The division here is correctly rounded with respect to the true value of π/180. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f64. const RADS_PER_DEG: f64 = consts::PI / 180.0; self * RADS_PER_DEG } diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index d57b1d433e5..610d9d8cf92 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -178,3 +178,18 @@ impl NotAllOnesHelper for u64 { impl NotAllOnesHelper for i64 { type Type = I64NotAllOnes; } + +define_valid_range_type! { + pub struct CodePointInner(u32 as u32 in 0..=0x10ffff); +} + +impl CodePointInner { + pub const ZERO: Self = CodePointInner::new(0).unwrap(); +} + +impl Default for CodePointInner { + #[inline] + fn default() -> Self { + Self::ZERO + } +} diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 10d9498d15e..c556d951034 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2447,7 +2447,7 @@ macro_rules! uint_impl { } /// Calculates `self` + `rhs` + `carry` and returns a tuple containing - /// the sum and the output carry. + /// the sum and the output carry (in that order). /// /// Performs "ternary addition" of two integer operands and a carry-in /// bit, and returns an output integer and a carry-out bit. This allows @@ -2465,8 +2465,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] - /// #[doc = concat!("// 3 MAX (a = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] #[doc = concat!("// + 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")] /// // --------- @@ -2483,7 +2481,7 @@ macro_rules! uint_impl { /// /// assert_eq!((sum1, sum0), (9, 6)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2559,8 +2557,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] - /// #[doc = concat!("// 9 6 (a = 9 × 2^", stringify!($BITS), " + 6)")] #[doc = concat!("// - 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")] /// // --------- @@ -2577,7 +2573,7 @@ macro_rules! uint_impl { /// #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2651,10 +2647,12 @@ macro_rules! uint_impl { /// indicating whether an arithmetic overflow would occur. If an /// overflow would have occurred then the wrapped value is returned. /// + /// If you want the *value* of the overflow, rather than just *whether* + /// an overflow occurred, see [`Self::carrying_mul`]. + /// /// # Examples /// - /// Please note that this example is shared among integer types, which is why why `u32` - /// is used. + /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` /// assert_eq!(5u32.overflowing_mul(2), (10, false)); @@ -2670,16 +2668,38 @@ macro_rules! uint_impl { (a as Self, b) } - /// Calculates the complete product `self * rhs` without the possibility to overflow. + /// Calculates the complete double-width product `self * rhs`. /// /// This returns the low-order (wrapping) bits and the high-order (overflow) bits - /// of the result as two separate values, in that order. + /// of the result as two separate values, in that order. As such, + /// `a.widening_mul(b).0` produces the same result as `a.wrapping_mul(b)`. + /// + /// If you also need to add a value and carry to the wide result, then you want + /// [`Self::carrying_mul_add`] instead. /// /// If you also need to add a carry to the wide result, then you want /// [`Self::carrying_mul`] instead. /// + /// If you just want to know *whether* the multiplication overflowed, then you + /// want [`Self::overflowing_mul`] instead. + /// /// # Examples /// + /// ``` + /// #![feature(bigint_helper_methods)] + #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")] + /// ``` + /// + /// Compared to other `*_mul` methods: + /// ``` + /// #![feature(bigint_helper_methods)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::checked_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), None);")] + /// ``` + /// /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` @@ -2706,14 +2726,13 @@ macro_rules! uint_impl { /// additional amount of overflow. This allows for chaining together multiple /// multiplications to create "big integers" which represent larger values. /// - /// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead. + /// If you also need to add a value, then use [`Self::carrying_mul_add`]. /// /// # Examples /// /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0)); /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0)); /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2)); @@ -2771,7 +2790,7 @@ macro_rules! uint_impl { /// 789_u16.wrapping_mul(456).wrapping_add(123), /// ); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2780,18 +2799,20 @@ macro_rules! uint_impl { Self::carrying_mul_add(self, rhs, carry, 0) } - /// Calculates the "full multiplication" `self * rhs + carry1 + carry2` - /// without the possibility to overflow. + /// Calculates the "full multiplication" `self * rhs + carry1 + carry2`. /// /// This returns the low-order (wrapping) bits and the high-order (overflow) bits /// of the result as two separate values, in that order. /// + /// This cannot overflow, as the double-width result has exactly enough + /// space for the largest possible result. This is equivalent to how, in + /// decimal, 9 × 9 + 9 + 9 = 81 + 18 = 99 = 9×10⁰ + 9×10¹ = 10² - 1. + /// /// Performs "long multiplication" which takes in an extra amount to add, and may return an /// additional amount of overflow. This allows for chaining together multiple /// multiplications to create "big integers" which represent larger values. /// - /// If you don't need either `carry`, then you can use [`Self::widening_mul`] instead, - /// and if you only need one `carry`, then you can use [`Self::carrying_mul`] instead. + /// If you don't need the `add` part, then you can use [`Self::carrying_mul`] instead. /// /// # Examples /// @@ -2799,7 +2820,6 @@ macro_rules! uint_impl { /// which explains why `u32` is used here. /// /// ``` - /// #![feature(bigint_helper_methods)] /// assert_eq!(5u32.carrying_mul_add(2, 0, 0), (10, 0)); /// assert_eq!(5u32.carrying_mul_add(2, 10, 10), (30, 0)); /// assert_eq!(1_000_000_000u32.carrying_mul_add(10, 0, 0), (1410065408, 2)); @@ -2816,8 +2836,6 @@ macro_rules! uint_impl { /// using `u8` for simplicity of the demonstration. /// /// ``` - /// #![feature(bigint_helper_methods)] - /// /// fn quadratic_mul<const N: usize>(a: [u8; N], b: [u8; N]) -> [u8; N] { /// let mut out = [0; N]; /// for j in 0..N { @@ -2832,13 +2850,13 @@ macro_rules! uint_impl { /// // -1 * -1 == 1 /// assert_eq!(quadratic_mul([0xFF; 3], [0xFF; 3]), [1, 0, 0]); /// - /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xCFFC982D); + /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xcffc982d); /// assert_eq!( /// quadratic_mul(u32::to_le_bytes(0x9e3779b9), u32::to_le_bytes(0x7f4a7c15)), - /// u32::to_le_bytes(0xCFFC982D) + /// u32::to_le_bytes(0xcffc982d) /// ); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index e83e77344cf..fa09409b6da 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1961,6 +1961,42 @@ impl<T> Option<T> { _ => None, } } + + /// Reduces two options into one, using the provided function if both are `Some`. + /// + /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`. + /// Otherwise, if only one of `self` and `other` is `Some`, that one is returned. + /// If both `self` and `other` are `None`, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_reduce)] + /// + /// let s12 = Some(12); + /// let s17 = Some(17); + /// let n = None; + /// let f = |a, b| a + b; + /// + /// assert_eq!(s12.reduce(s17, f), Some(29)); + /// assert_eq!(s12.reduce(n, f), Some(12)); + /// assert_eq!(n.reduce(s17, f), Some(17)); + /// assert_eq!(n.reduce(n, f), None); + /// ``` + #[unstable(feature = "option_reduce", issue = "144273")] + pub fn reduce<U, R, F>(self, other: Option<U>, f: F) -> Option<R> + where + T: Into<R>, + U: Into<R>, + F: FnOnce(T, U) -> R, + { + match (self, other) { + (Some(a), Some(b)) => Some(f(a, b)), + (Some(a), _) => Some(a.into()), + (_, Some(b)) => Some(b.into()), + _ => None, + } + } } impl<T, U> Option<(T, U)> { diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index cafdcfa2c2e..7a68d393906 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -39,7 +39,7 @@ use crate::ptr::NonNull; pub struct Location<'a> { // A raw pointer is used rather than a reference because the pointer is valid for one more byte // than the length stored in this pointer; the additional byte is the NUL-terminator used by - // `Location::file_with_nul`. + // `Location::file_as_c_str`. filename: NonNull<str>, line: u32, col: u32, @@ -195,7 +195,7 @@ impl<'a> Location<'a> { #[must_use] #[unstable(feature = "file_with_nul", issue = "141727")] #[inline] - pub const fn file_with_nul(&self) -> &'a CStr { + pub const fn file_as_c_str(&self) -> &'a CStr { let filename = self.filename.as_ptr(); // SAFETY: The filename is valid for `filename_len+1` bytes, so this addition can't diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 0deac3621e8..dc3ec3fd199 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -106,6 +106,9 @@ pub const fn metadata<T: PointeeSized>(ptr: *const T) -> <T as Pointee>::Metadat /// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements. /// For trait objects, the metadata must come from a pointer to the same underlying erased type. /// +/// If you are attempting to deconstruct a DST in a generic context to be reconstructed later, +/// a thin pointer can always be obtained by casting `*const T` to `*const ()`. +/// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] #[inline] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f5c490ca7ce..6fc85a83e17 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -914,6 +914,7 @@ pub const fn dangling<T>() -> *const T { #[must_use] #[stable(feature = "strict_provenance", since = "1.84.0")] #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] +#[allow(integer_to_ptr_transmutes)] // Expected semantics here. pub const fn without_provenance_mut<T>(addr: usize) -> *mut T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index 4c8231a2286..1677c849ae4 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -124,12 +124,7 @@ impl fmt::Display for Utf8Error { } #[stable(feature = "rust1", since = "1.0.0")] -impl Error for Utf8Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "invalid utf-8: corrupt contents" - } -} +impl Error for Utf8Error {} /// An error returned when parsing a `bool` using [`from_str`] fails /// @@ -147,9 +142,4 @@ impl fmt::Display for ParseBoolError { } #[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseBoolError { - #[allow(deprecated)] - fn description(&self) -> &str { - "failed to parse bool" - } -} +impl Error for ParseBoolError {} diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1b6e84175b9..f1db385e212 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -396,7 +396,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(round_char_boundary)] /// let s = "❤️🧡💛💚💙💜"; /// assert_eq!(s.len(), 26); /// assert!(!s.is_char_boundary(13)); @@ -405,7 +404,8 @@ impl str { /// assert_eq!(closest, 10); /// assert_eq!(&s[..closest], "❤️🧡"); /// ``` - #[unstable(feature = "round_char_boundary", issue = "93743")] + #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn floor_char_boundary(&self, index: usize) -> usize { if index >= self.len() { @@ -439,7 +439,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(round_char_boundary)] /// let s = "❤️🧡💛💚💙💜"; /// assert_eq!(s.len(), 26); /// assert!(!s.is_char_boundary(13)); @@ -448,7 +447,8 @@ impl str { /// assert_eq!(closest, 14); /// assert_eq!(&s[..closest], "❤️🧡💛"); /// ``` - #[unstable(feature = "round_char_boundary", issue = "93743")] + #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn ceil_char_boundary(&self, index: usize) -> usize { if index >= self.len() { @@ -3072,7 +3072,7 @@ impl str { /// for example references to `Box<str>` or `Arc<str>`. #[inline] #[unstable(feature = "str_as_str", issue = "130366")] - pub fn as_str(&self) -> &str { + pub const fn as_str(&self) -> &str { self } } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 44a6895f90a..7bd68bcd0bc 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2199,7 +2199,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); @@ -2209,7 +2208,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order) @@ -2240,7 +2239,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let array = [1i32, 2i32]; @@ -2254,7 +2252,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order) @@ -2279,7 +2277,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); @@ -2289,7 +2286,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2315,7 +2312,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let mut arr = [0i64, 1]; @@ -2325,7 +2321,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2361,7 +2357,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2376,7 +2371,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2412,7 +2407,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2426,7 +2420,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2462,7 +2456,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2474,7 +2467,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 0cc570f4b73..f37e47f132d 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -927,7 +927,7 @@ impl Duration { pub fn from_secs_f64(secs: f64) -> Duration { match Duration::try_from_secs_f64(secs) { Ok(v) => v, - Err(e) => panic!("{}", e.description()), + Err(e) => panic!("{e}"), } } @@ -964,7 +964,7 @@ impl Duration { pub fn from_secs_f32(secs: f32) -> Duration { match Duration::try_from_secs_f32(secs) { Ok(v) => v, - Err(e) => panic!("{}", e.description()), + Err(e) => panic!("{e}"), } } @@ -1445,8 +1445,9 @@ pub struct TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind, } -impl TryFromFloatSecsError { - const fn description(&self) -> &'static str { +#[stable(feature = "duration_checked_float", since = "1.66.0")] +impl fmt::Display for TryFromFloatSecsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { TryFromFloatSecsErrorKind::Negative => { "cannot convert float seconds to Duration: value is negative" @@ -1455,13 +1456,7 @@ impl TryFromFloatSecsError { "cannot convert float seconds to Duration: value is either too big or NaN" } } - } -} - -#[stable(feature = "duration_checked_float", since = "1.66.0")] -impl fmt::Display for TryFromFloatSecsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.description().fmt(f) + .fmt(f) } } diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs new file mode 100644 index 00000000000..de0dfa560a3 --- /dev/null +++ b/library/core/src/wtf8.rs @@ -0,0 +1,597 @@ +//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/). +//! +//! This library uses Rust’s type system to maintain +//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed), +//! like the `String` and `&str` types do for UTF-8. +//! +//! Since [WTF-8 must not be used +//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience), +//! this library deliberately does not provide access to the underlying bytes +//! of WTF-8 strings, +//! nor can it decode WTF-8 from arbitrary bytes. +//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points. +#![unstable( + feature = "wtf8_internals", + issue = "none", + reason = "this is internal code for representing OsStr on some platforms and not a public API" +)] +// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait +// implementations, so, we'll have to add more doc(hidden)s anyway +#![doc(hidden)] + +use crate::char::{MAX_LEN_UTF16, encode_utf16_raw}; +use crate::clone::CloneToUninit; +use crate::fmt::{self, Write}; +use crate::hash::{Hash, Hasher}; +use crate::iter::FusedIterator; +use crate::num::niche_types::CodePointInner; +use crate::str::next_code_point; +use crate::{ops, slice, str}; + +/// A Unicode code point: from U+0000 to U+10FFFF. +/// +/// Compares with the `char` type, +/// which represents a Unicode scalar value: +/// a code point that is not a surrogate (U+D800 to U+DFFF). +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] +#[doc(hidden)] +pub struct CodePoint(CodePointInner); + +/// Format the code point as `U+` followed by four to six hexadecimal digits. +/// Example: `U+1F4A9` +impl fmt::Debug for CodePoint { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "U+{:04X}", self.0.as_inner()) + } +} + +impl CodePoint { + /// Unsafely creates a new `CodePoint` without checking the value. + /// + /// Only use when `value` is known to be less than or equal to 0x10FFFF. + #[inline] + pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint { + // SAFETY: Guaranteed by caller. + CodePoint(unsafe { CodePointInner::new_unchecked(value) }) + } + + /// Creates a new `CodePoint` if the value is a valid code point. + /// + /// Returns `None` if `value` is above 0x10FFFF. + #[inline] + pub fn from_u32(value: u32) -> Option<CodePoint> { + Some(CodePoint(CodePointInner::new(value)?)) + } + + /// Creates a new `CodePoint` from a `char`. + /// + /// Since all Unicode scalar values are code points, this always succeeds. + #[inline] + pub fn from_char(value: char) -> CodePoint { + // SAFETY: All char are valid for this type. + unsafe { CodePoint::from_u32_unchecked(value as u32) } + } + + /// Returns the numeric value of the code point. + #[inline] + pub fn to_u32(&self) -> u32 { + self.0.as_inner() + } + + /// Returns the numeric value of the code point if it is a leading surrogate. + #[inline] + pub fn to_lead_surrogate(&self) -> Option<u16> { + match self.to_u32() { + lead @ 0xD800..=0xDBFF => Some(lead as u16), + _ => None, + } + } + + /// Returns the numeric value of the code point if it is a trailing surrogate. + #[inline] + pub fn to_trail_surrogate(&self) -> Option<u16> { + match self.to_u32() { + trail @ 0xDC00..=0xDFFF => Some(trail as u16), + _ => None, + } + } + + /// Optionally returns a Unicode scalar value for the code point. + /// + /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF). + #[inline] + pub fn to_char(&self) -> Option<char> { + match self.to_u32() { + 0xD800..=0xDFFF => None, + // SAFETY: We explicitly check that the char is valid. + valid => Some(unsafe { char::from_u32_unchecked(valid) }), + } + } + + /// Returns a Unicode scalar value for the code point. + /// + /// Returns `'\u{FFFD}'` (the replacement character “�”) + /// if the code point is a surrogate (from U+D800 to U+DFFF). + #[inline] + pub fn to_char_lossy(&self) -> char { + self.to_char().unwrap_or(char::REPLACEMENT_CHARACTER) + } +} + +/// A borrowed slice of well-formed WTF-8 data. +/// +/// Similar to `&str`, but can additionally contain surrogate code points +/// if they’re not in a surrogate pair. +#[derive(Eq, Ord, PartialEq, PartialOrd)] +#[repr(transparent)] +#[rustc_has_incoherent_inherent_impls] +#[doc(hidden)] +pub struct Wtf8 { + bytes: [u8], +} + +impl AsRef<[u8]> for Wtf8 { + #[inline] + fn as_ref(&self) -> &[u8] { + &self.bytes + } +} + +/// Formats the string in double quotes, with characters escaped according to +/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, +/// where each `x` is a hexadecimal digit. +impl fmt::Debug for Wtf8 { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { + use crate::fmt::Write; + for c in s.chars().flat_map(|c| c.escape_debug()) { + f.write_char(c)? + } + Ok(()) + } + + formatter.write_str("\"")?; + let mut pos = 0; + while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) { + // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes. + write_str_escaped(formatter, unsafe { + str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos]) + })?; + write!(formatter, "\\u{{{:x}}}", surrogate)?; + pos = surrogate_pos + 3; + } + + // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8. + write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?; + formatter.write_str("\"") + } +} + +/// Formats the string with unpaired surrogates substituted with the replacement +/// character, U+FFFD. +impl fmt::Display for Wtf8 { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + let wtf8_bytes = &self.bytes; + let mut pos = 0; + loop { + match self.next_surrogate(pos) { + Some((surrogate_pos, _)) => { + // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes. + formatter.write_str(unsafe { + str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos]) + })?; + formatter.write_char(char::REPLACEMENT_CHARACTER)?; + pos = surrogate_pos + 3; + } + None => { + // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8. + let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) }; + if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) } + } + } + } + } +} + +impl Wtf8 { + /// Creates a WTF-8 slice from a UTF-8 `&str` slice. + #[inline] + pub fn from_str(value: &str) -> &Wtf8 { + // SAFETY: Since WTF-8 is a superset of UTF-8, this always is valid. + unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) } + } + + /// Creates a WTF-8 slice from a WTF-8 byte slice. + /// + /// Since the byte slice is not checked for valid WTF-8, this functions is + /// marked unsafe. + #[inline] + pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 { + // SAFETY: start with &[u8], end with fancy &[u8] + unsafe { &*(value as *const [u8] as *const Wtf8) } + } + + /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice. + /// + /// Since the byte slice is not checked for valid WTF-8, this functions is + /// marked unsafe. + #[inline] + pub unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 { + // SAFETY: start with &mut [u8], end with fancy &mut [u8] + unsafe { &mut *(value as *mut [u8] as *mut Wtf8) } + } + + /// Returns the length, in WTF-8 bytes. + #[inline] + pub fn len(&self) -> usize { + self.bytes.len() + } + + #[inline] + pub fn is_empty(&self) -> bool { + self.bytes.is_empty() + } + + /// Returns the code point at `position` if it is in the ASCII range, + /// or `b'\xFF'` otherwise. + /// + /// # Panics + /// + /// Panics if `position` is beyond the end of the string. + #[inline] + pub fn ascii_byte_at(&self, position: usize) -> u8 { + match self.bytes[position] { + ascii_byte @ 0x00..=0x7F => ascii_byte, + _ => 0xFF, + } + } + + /// Returns an iterator for the string’s code points. + #[inline] + pub fn code_points(&self) -> Wtf8CodePoints<'_> { + Wtf8CodePoints { bytes: self.bytes.iter() } + } + + /// Access raw bytes of WTF-8 data + #[inline] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes + } + + /// Tries to convert the string to UTF-8 and return a `&str` slice. + /// + /// Returns `None` if the string contains surrogates. + /// + /// This does not copy the data. + #[inline] + pub fn as_str(&self) -> Result<&str, str::Utf8Error> { + str::from_utf8(&self.bytes) + } + + /// Converts the WTF-8 string to potentially ill-formed UTF-16 + /// and return an iterator of 16-bit code units. + /// + /// This is lossless: + /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units + /// would always return the original WTF-8 string. + #[inline] + pub fn encode_wide(&self) -> EncodeWide<'_> { + EncodeWide { code_points: self.code_points(), extra: 0 } + } + + #[inline] + pub fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> { + let mut iter = self.bytes[pos..].iter(); + loop { + let b = *iter.next()?; + if b < 0x80 { + pos += 1; + } else if b < 0xE0 { + iter.next(); + pos += 2; + } else if b == 0xED { + match (iter.next(), iter.next()) { + (Some(&b2), Some(&b3)) if b2 >= 0xA0 => { + return Some((pos, decode_surrogate(b2, b3))); + } + _ => pos += 3, + } + } else if b < 0xF0 { + iter.next(); + iter.next(); + pos += 3; + } else { + iter.next(); + iter.next(); + iter.next(); + pos += 4; + } + } + } + + #[inline] + pub fn final_lead_surrogate(&self) -> Option<u16> { + match self.bytes { + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), + _ => None, + } + } + + #[inline] + pub fn initial_trail_surrogate(&self) -> Option<u16> { + match self.bytes { + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)), + _ => None, + } + } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.bytes.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.bytes.make_ascii_uppercase() + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.bytes.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.bytes.eq_ignore_ascii_case(&other.bytes) + } +} + +/// Returns a slice of the given string for the byte range \[`begin`..`end`). +/// +/// # Panics +/// +/// Panics when `begin` and `end` do not point to code point boundaries, +/// or point beyond the end of the string. +impl ops::Index<ops::Range<usize>> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, range: ops::Range<usize>) -> &Wtf8 { + if range.start <= range.end + && self.is_code_point_boundary(range.start) + && self.is_code_point_boundary(range.end) + { + // SAFETY: is_code_point_boundary checks that the index is valid + unsafe { slice_unchecked(self, range.start, range.end) } + } else { + slice_error_fail(self, range.start, range.end) + } + } +} + +/// Returns a slice of the given string from byte `begin` to its end. +/// +/// # Panics +/// +/// Panics when `begin` is not at a code point boundary, +/// or is beyond the end of the string. +impl ops::Index<ops::RangeFrom<usize>> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 { + if self.is_code_point_boundary(range.start) { + // SAFETY: is_code_point_boundary checks that the index is valid + unsafe { slice_unchecked(self, range.start, self.len()) } + } else { + slice_error_fail(self, range.start, self.len()) + } + } +} + +/// Returns a slice of the given string from its beginning to byte `end`. +/// +/// # Panics +/// +/// Panics when `end` is not at a code point boundary, +/// or is beyond the end of the string. +impl ops::Index<ops::RangeTo<usize>> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 { + if self.is_code_point_boundary(range.end) { + // SAFETY: is_code_point_boundary checks that the index is valid + unsafe { slice_unchecked(self, 0, range.end) } + } else { + slice_error_fail(self, 0, range.end) + } + } +} + +impl ops::Index<ops::RangeFull> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, _range: ops::RangeFull) -> &Wtf8 { + self + } +} + +#[inline] +fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 { + // The first byte is assumed to be 0xED + 0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F +} + +impl Wtf8 { + /// Copied from str::is_char_boundary + #[inline] + pub fn is_code_point_boundary(&self, index: usize) -> bool { + if index == 0 { + return true; + } + match self.bytes.get(index) { + None => index == self.len(), + Some(&b) => (b as i8) >= -0x40, + } + } + + /// Verify that `index` is at the edge of either a valid UTF-8 codepoint + /// (i.e. a codepoint that's not a surrogate) or of the whole string. + /// + /// These are the cases currently permitted by `OsStr::self_encoded_bytes`. + /// Splitting between surrogates is valid as far as WTF-8 is concerned, but + /// we do not permit it in the public API because WTF-8 is considered an + /// implementation detail. + #[track_caller] + #[inline] + pub fn check_utf8_boundary(&self, index: usize) { + if index == 0 { + return; + } + match self.bytes.get(index) { + Some(0xED) => (), // Might be a surrogate + Some(&b) if (b as i8) >= -0x40 => return, + Some(_) => panic!("byte index {index} is not a codepoint boundary"), + None if index == self.len() => return, + None => panic!("byte index {index} is out of bounds"), + } + if self.bytes[index + 1] >= 0xA0 { + // There's a surrogate after index. Now check before index. + if index >= 3 && self.bytes[index - 3] == 0xED && self.bytes[index - 2] >= 0xA0 { + panic!("byte index {index} lies between surrogate codepoints"); + } + } + } +} + +/// Copied from core::str::raw::slice_unchecked +#[inline] +unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { + // SAFETY: memory layout of a &[u8] and &Wtf8 are the same + unsafe { + let len = end - begin; + let start = s.as_bytes().as_ptr().add(begin); + Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len)) + } +} + +/// Copied from core::str::raw::slice_error_fail +#[inline(never)] +fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! { + assert!(begin <= end); + panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary"); +} + +/// Iterator for the code points of a WTF-8 string. +/// +/// Created with the method `.code_points()`. +#[derive(Clone)] +#[doc(hidden)] +pub struct Wtf8CodePoints<'a> { + bytes: slice::Iter<'a, u8>, +} + +impl Iterator for Wtf8CodePoints<'_> { + type Item = CodePoint; + + #[inline] + fn next(&mut self) -> Option<CodePoint> { + // SAFETY: `self.bytes` has been created from a WTF-8 string + unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint::from_u32_unchecked(c)) } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.bytes.len(); + (len.saturating_add(3) / 4, Some(len)) + } +} + +impl fmt::Debug for Wtf8CodePoints<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Wtf8CodePoints") + // SAFETY: We always leave the string in a valid state after each iteration. + .field(&unsafe { Wtf8::from_bytes_unchecked(self.bytes.as_slice()) }) + .finish() + } +} + +/// Generates a wide character sequence for potentially ill-formed UTF-16. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +#[doc(hidden)] +pub struct EncodeWide<'a> { + code_points: Wtf8CodePoints<'a>, + extra: u16, +} + +// Copied from libunicode/u_str.rs +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EncodeWide<'_> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option<u16> { + if self.extra != 0 { + let tmp = self.extra; + self.extra = 0; + return Some(tmp); + } + + let mut buf = [0; MAX_LEN_UTF16]; + self.code_points.next().map(|code_point| { + let n = encode_utf16_raw(code_point.to_u32(), &mut buf).len(); + if n == 2 { + self.extra = buf[1]; + } + buf[0] + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, high) = self.code_points.size_hint(); + let ext = (self.extra != 0) as usize; + // every code point gets either one u16 or two u16, + // so this iterator is between 1 or 2 times as + // long as the underlying iterator. + (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext))) + } +} + +impl fmt::Debug for EncodeWide<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EncodeWide").finish_non_exhaustive() + } +} + +#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")] +impl FusedIterator for EncodeWide<'_> {} + +impl Hash for CodePoint { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + self.0.hash(state) + } +} + +impl Hash for Wtf8 { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for Wtf8 { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + // SAFETY: we're just a transparent wrapper around [u8] + unsafe { self.bytes.clone_to_uninit(dst) } + } +} |
