diff options
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/array/mod.rs | 33 | ||||
| -rw-r--r-- | library/core/src/cell.rs | 6 | ||||
| -rw-r--r-- | library/core/src/char/methods.rs | 90 | ||||
| -rw-r--r-- | library/core/src/char/mod.rs | 2 | ||||
| -rw-r--r-- | library/core/src/clone.rs | 2 | ||||
| -rw-r--r-- | library/core/src/macros/mod.rs | 7 | ||||
| -rw-r--r-- | library/core/src/num/mod.rs | 4 |
7 files changed, 101 insertions, 43 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 28329bb0908..efa7bed7c8e 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -55,12 +55,16 @@ pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] { from_trusted_iterator(repeat_n(val, N)) } -/// Creates an array of type [T; N], where each element `T` is the returned value from `cb` -/// using that element's index. +/// Creates an array where each element is produced by calling `f` with +/// that element's index while walking forward through the array. /// -/// # Arguments +/// This is essentially the same as writing +/// ```text +/// [f(0), f(1), f(2), …, f(N - 2), f(N - 1)] +/// ``` +/// and is similar to `(0..i).map(f)`, just for arrays not iterators. /// -/// * `cb`: Callback where the passed argument is the current array index. +/// If `N == 0`, this produces an empty array without ever calling `f`. /// /// # Example /// @@ -82,13 +86,30 @@ pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] { /// // indexes are: 0 1 2 3 4 /// assert_eq!(bool_arr, [true, false, true, false, true]); /// ``` +/// +/// You can also capture things, for example to create an array full of clones +/// where you can't just use `[item; N]` because it's not `Copy`: +/// ``` +/// # // TBH `array::repeat` would be better for this, but it's not stable yet. +/// let my_string = String::from("Hello"); +/// let clones: [String; 42] = std::array::from_fn(|_| my_string.clone()); +/// assert!(clones.iter().all(|x| *x == my_string)); +/// ``` +/// +/// The array is generated in ascending index order, starting from the front +/// and going towards the back, so you can use closures with mutable state: +/// ``` +/// let mut state = 1; +/// let a = std::array::from_fn(|_| { let x = state; state *= 2; x }); +/// assert_eq!(a, [1, 2, 4, 8, 16, 32]); +/// ``` #[inline] #[stable(feature = "array_from_fn", since = "1.63.0")] -pub fn from_fn<T, const N: usize, F>(cb: F) -> [T; N] +pub fn from_fn<T, const N: usize, F>(f: F) -> [T; N] where F: FnMut(usize) -> T, { - try_from_fn(NeverShortCircuit::wrap_mut_1(cb)).0 + try_from_fn(NeverShortCircuit::wrap_mut_1(f)).0 } /// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 09117e4968d..17231df731d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1156,7 +1156,9 @@ impl<T: ?Sized> RefCell<T> { /// Since this method borrows `RefCell` mutably, it is statically guaranteed /// that no borrows to the underlying data exist. The dynamic checks inherent /// in [`borrow_mut`] and most other methods of `RefCell` are therefore - /// unnecessary. + /// unnecessary. Note that this method does not reset the borrowing state if borrows were previously leaked + /// (e.g., via [`forget()`] on a [`Ref`] or [`RefMut`]). For that purpose, + /// consider using the unstable [`undo_leak`] method. /// /// This method can only be called if `RefCell` can be mutably borrowed, /// which in general is only the case directly after the `RefCell` has @@ -1167,6 +1169,8 @@ impl<T: ?Sized> RefCell<T> { /// Use [`borrow_mut`] to get mutable access to the underlying data then. /// /// [`borrow_mut`]: RefCell::borrow_mut() + /// [`forget()`]: mem::forget + /// [`undo_leak`]: RefCell::undo_leak() /// /// # Examples /// diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index c575e08c54a..042925a352f 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1806,39 +1806,71 @@ const fn len_utf16(code: u32) -> usize { #[inline] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { let len = len_utf8(code); - match (len, &mut *dst) { - (1, [a, ..]) => { - *a = code as u8; - } - (2, [a, b, ..]) => { - *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - *b = (code & 0x3F) as u8 | TAG_CONT; - } - (3, [a, b, c, ..]) => { - *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *b = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *c = (code & 0x3F) as u8 | TAG_CONT; - } - (4, [a, b, c, d, ..]) => { - *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - *b = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *d = (code & 0x3F) as u8 | TAG_CONT; - } - _ => { - const_panic!( - "encode_utf8: buffer does not have enough bytes to encode code point", - "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", - code: u32 = code, - len: usize = len, - dst_len: usize = dst.len(), - ) - } - }; + if dst.len() < len { + const_panic!( + "encode_utf8: buffer does not have enough bytes to encode code point", + "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", + code: u32 = code, + len: usize = len, + dst_len: usize = dst.len(), + ); + } + + // SAFETY: `dst` is checked to be at least the length needed to encode the codepoint. + unsafe { encode_utf8_raw_unchecked(code, dst.as_mut_ptr()) }; + // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds. unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } } +/// Encodes a raw `u32` value as UTF-8 into the byte buffer pointed to by `dst`. +/// +/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range. +/// (Creating a `char` in the surrogate range is UB.) +/// The result is valid [generalized UTF-8] but not valid UTF-8. +/// +/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8 +/// +/// # Safety +/// +/// The behavior is undefined if the buffer pointed to by `dst` is not +/// large enough to hold the encoded codepoint. A buffer of length four +/// is large enough to encode any `char`. +/// +/// For a safe version of this function, see the [`encode_utf8_raw`] function. +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +#[doc(hidden)] +#[inline] +pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) { + let len = len_utf8(code); + // 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(), + } + } +} + /// Encodes a raw `u32` value as native endian UTF-16 into the provided `u16` buffer, /// and then returns the subslice of the buffer that contains the encoded character. /// diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 088c709f1a2..5b9f0e2143f 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -38,7 +38,7 @@ pub use self::decode::{DecodeUtf16, DecodeUtf16Error}; #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf16_raw; // perma-unstable #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -pub use self::methods::encode_utf8_raw; // perma-unstable +pub use self::methods::{encode_utf8_raw, encode_utf8_raw_unchecked}; // perma-unstable #[rustfmt::skip] use crate::ascii; diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 374a56f1252..c237ac84cf4 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -427,7 +427,7 @@ pub unsafe trait CloneToUninit { /// read or dropped, because even if it was previously valid, it may have been partially /// overwritten. /// - /// The caller may wish to to take care to deallocate the allocation pointed to by `dest`, + /// The caller may wish to take care to deallocate the allocation pointed to by `dest`, /// if applicable, to avoid a memory leak (but this is not a requirement). /// /// Implementors should avoid leaking values by, upon unwinding, dropping all component values diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7f0949f3ad8..330b4098764 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -237,9 +237,10 @@ pub macro assert_matches { /// ``` #[unstable(feature = "cfg_match", issue = "115585")] #[rustc_diagnostic_item = "cfg_match"] +#[rustc_macro_transparency = "semitransparent"] pub macro cfg_match { ({ $($tt:tt)* }) => {{ - cfg_match! { $($tt)* } + $crate::cfg_match! { $($tt)* } }}, (_ => { $($output:tt)* }) => { $($output)* @@ -249,10 +250,10 @@ pub macro cfg_match { $($( $rest:tt )+)? ) => { #[cfg($cfg)] - cfg_match! { _ => $output } + $crate::cfg_match! { _ => $output } $( #[cfg(not($cfg))] - cfg_match! { $($rest)+ } + $crate::cfg_match! { $($rest)+ } )? }, } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9c67c37a3dd..348457e2c00 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -99,8 +99,8 @@ macro_rules! i8_xe_bytes_doc { **Note**: This function is meaningless on `i8`. Byte order does not exist as a concept for byte-sized integers. This function is only provided in symmetry -with larger integer types. You can cast from and to `u8` using `as i8` and `as -u8`. +with larger integer types. You can cast from and to `u8` using +[`cast_signed`](u8::cast_signed) and [`cast_unsigned`](Self::cast_unsigned). " }; |
