]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #74381 - mbrubeck:docs, r=Mark-Simulacrum
authorManish Goregaokar <manishsmail@gmail.com>
Thu, 16 Jul 2020 07:01:13 +0000 (00:01 -0700)
committerGitHub <noreply@github.com>
Thu, 16 Jul 2020 07:01:13 +0000 (00:01 -0700)
Update docs for str::as_bytes_mut.

* Add "Safety" section describing UTF-8 invariant.

* Remove mention of `from_utf8_mut`.  It is not necessary to call
  a function to convert the byte slice back to a string slice.  The
  original string becomes accessible again after the byte slice is
  no longer used (as shown in the example code).

1  2 
src/libcore/str/mod.rs

diff --combined src/libcore/str/mod.rs
index 393911675c73e8d1e2311beff926924e13611ded,10721ce6165d6d52e52a03f407cb22849469fb92..86e8d5c42b7adae3c150099d87a0eac112ea6372
@@@ -1731,8 -1731,7 +1731,8 @@@ Section: Trait implementation
  mod traits {
      use crate::cmp::Ordering;
      use crate::ops;
 -    use crate::slice::{self, SliceIndex};
 +    use crate::ptr;
 +    use crate::slice::SliceIndex;
  
      /// Implements ordering of strings.
      ///
      ///
      /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`.
      #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 -    impl SliceIndex<str> for ops::RangeFull {
 +    unsafe impl SliceIndex<str> for ops::RangeFull {
          type Output = str;
          #[inline]
          fn get(self, slice: &str) -> Option<&Self::Output> {
              Some(slice)
          }
          #[inline]
 -        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
 +        unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
              slice
          }
          #[inline]
 -        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
 +        unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
              slice
          }
          #[inline]
      /// // &s[3 .. 100];
      /// ```
      #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 -    impl SliceIndex<str> for ops::Range<usize> {
 +    unsafe impl SliceIndex<str> for ops::Range<usize> {
          type Output = str;
          #[inline]
          fn get(self, slice: &str) -> Option<&Self::Output> {
                  && slice.is_char_boundary(self.start)
                  && slice.is_char_boundary(self.end)
              {
 -                // SAFETY: just checked that `start` and `end` are on a char boundary.
 -                Some(unsafe { self.get_unchecked(slice) })
 +                // SAFETY: just checked that `start` and `end` are on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                // We also checked char boundaries, so this is valid UTF-8.
 +                Some(unsafe { &*self.get_unchecked(slice) })
              } else {
                  None
              }
                  && slice.is_char_boundary(self.end)
              {
                  // SAFETY: just checked that `start` and `end` are on a char boundary.
 -                Some(unsafe { self.get_unchecked_mut(slice) })
 +                // We know the pointer is unique because we got it from `slice`.
 +                Some(unsafe { &mut *self.get_unchecked_mut(slice) })
              } else {
                  None
              }
          }
          #[inline]
 -        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
 +        unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
 +            let slice = slice as *const [u8];
              // SAFETY: the caller guarantees that `self` is in bounds of `slice`
              // which satisfies all the conditions for `add`.
              let ptr = unsafe { slice.as_ptr().add(self.start) };
              let len = self.end - self.start;
 -            // SAFETY: as the caller guarantees that `self` is in bounds of `slice`,
 -            // we can safely construct a subslice with `from_raw_parts` and use it
 -            // since we return a shared thus immutable reference.
 -            // The call to `from_utf8_unchecked` is safe since the data comes from
 -            // a `str` which is guaranteed to be valid utf8, since the caller
 -            // must guarantee that `self.start` and `self.end` are char boundaries.
 -            unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
 +            ptr::slice_from_raw_parts(ptr, len) as *const str
          }
          #[inline]
 -        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
 +        unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
 +            let slice = slice as *mut [u8];
              // SAFETY: see comments for `get_unchecked`.
              let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
              let len = self.end - self.start;
 -            // SAFETY: mostly identical to the comments for `get_unchecked`, except that we
 -            // can return a mutable reference since the caller passed a mutable reference
 -            // and is thus guaranteed to have exclusive write access to `slice`.
 -            unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) }
 +            ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
          }
          #[inline]
          fn index(self, slice: &str) -> &Self::Output {
                  && slice.is_char_boundary(self.start)
                  && slice.is_char_boundary(self.end)
              {
 -                // SAFETY: just checked that `start` and `end` are on a char boundary.
 -                unsafe { self.get_unchecked_mut(slice) }
 +                // SAFETY: just checked that `start` and `end` are on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                unsafe { &mut *self.get_unchecked_mut(slice) }
              } else {
                  super::slice_error_fail(slice, self.start, self.end)
              }
      /// Panics if `end` does not point to the starting byte offset of a
      /// character (as defined by `is_char_boundary`), or if `end > len`.
      #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 -    impl SliceIndex<str> for ops::RangeTo<usize> {
 +    unsafe impl SliceIndex<str> for ops::RangeTo<usize> {
          type Output = str;
          #[inline]
          fn get(self, slice: &str) -> Option<&Self::Output> {
              if slice.is_char_boundary(self.end) {
 -                // SAFETY: just checked that `end` is on a char boundary.
 -                Some(unsafe { self.get_unchecked(slice) })
 +                // SAFETY: just checked that `end` is on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                Some(unsafe { &*self.get_unchecked(slice) })
              } else {
                  None
              }
          #[inline]
          fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
              if slice.is_char_boundary(self.end) {
 -                // SAFETY: just checked that `end` is on a char boundary.
 -                Some(unsafe { self.get_unchecked_mut(slice) })
 +                // SAFETY: just checked that `end` is on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                Some(unsafe { &mut *self.get_unchecked_mut(slice) })
              } else {
                  None
              }
          }
          #[inline]
 -        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
 +        unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
 +            let slice = slice as *const [u8];
              let ptr = slice.as_ptr();
 -            // SAFETY: as the caller guarantees that `self` is in bounds of `slice`,
 -            // we can safely construct a subslice with `from_raw_parts` and use it
 -            // since we return a shared thus immutable reference.
 -            // The call to `from_utf8_unchecked` is safe since the data comes from
 -            // a `str` which is guaranteed to be valid utf8, since the caller
 -            // must guarantee that `self.end` is a char boundary.
 -            unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end)) }
 +            ptr::slice_from_raw_parts(ptr, self.end) as *const str
          }
          #[inline]
 -        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
 +        unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
 +            let slice = slice as *mut [u8];
              let ptr = slice.as_mut_ptr();
 -            // SAFETY: mostly identical to `get_unchecked`, except that we can safely
 -            // return a mutable reference since the caller passed a mutable reference
 -            // and is thus guaranteed to have exclusive write access to `slice`.
 -            unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, self.end)) }
 +            ptr::slice_from_raw_parts_mut(ptr, self.end) as *mut str
          }
          #[inline]
          fn index(self, slice: &str) -> &Self::Output {
          #[inline]
          fn index_mut(self, slice: &mut str) -> &mut Self::Output {
              if slice.is_char_boundary(self.end) {
 -                // SAFETY: just checked that `end` is on a char boundary.
 -                unsafe { self.get_unchecked_mut(slice) }
 +                // SAFETY: just checked that `end` is on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                unsafe { &mut *self.get_unchecked_mut(slice) }
              } else {
                  super::slice_error_fail(slice, 0, self.end)
              }
      /// Panics if `begin` does not point to the starting byte offset of
      /// a character (as defined by `is_char_boundary`), or if `begin >= len`.
      #[stable(feature = "str_checked_slicing", since = "1.20.0")]
 -    impl SliceIndex<str> for ops::RangeFrom<usize> {
 +    unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
          type Output = str;
          #[inline]
          fn get(self, slice: &str) -> Option<&Self::Output> {
              if slice.is_char_boundary(self.start) {
 -                // SAFETY: just checked that `start` is on a char boundary.
 -                Some(unsafe { self.get_unchecked(slice) })
 +                // SAFETY: just checked that `start` is on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                Some(unsafe { &*self.get_unchecked(slice) })
              } else {
                  None
              }
          #[inline]
          fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
              if slice.is_char_boundary(self.start) {
 -                // SAFETY: just checked that `start` is on a char boundary.
 -                Some(unsafe { self.get_unchecked_mut(slice) })
 +                // SAFETY: just checked that `start` is on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                Some(unsafe { &mut *self.get_unchecked_mut(slice) })
              } else {
                  None
              }
          }
          #[inline]
 -        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
 +        unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
 +            let slice = slice as *const [u8];
              // SAFETY: the caller guarantees that `self` is in bounds of `slice`
              // which satisfies all the conditions for `add`.
              let ptr = unsafe { slice.as_ptr().add(self.start) };
              let len = slice.len() - self.start;
 -            // SAFETY: as the caller guarantees that `self` is in bounds of `slice`,
 -            // we can safely construct a subslice with `from_raw_parts` and use it
 -            // since we return a shared thus immutable reference.
 -            // The call to `from_utf8_unchecked` is safe since the data comes from
 -            // a `str` which is guaranteed to be valid utf8, since the caller
 -            // must guarantee that `self.start` is a char boundary.
 -            unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
 +            ptr::slice_from_raw_parts(ptr, len) as *const str
          }
          #[inline]
 -        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
 +        unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
 +            let slice = slice as *mut [u8];
              // SAFETY: identical to `get_unchecked`.
              let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
              let len = slice.len() - self.start;
 -            // SAFETY: mostly identical to `get_unchecked`, except that we can safely
 -            // return a mutable reference since the caller passed a mutable reference
 -            // and is thus guaranteed to have exclusive write access to `slice`.
 -            unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) }
 +            ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
          }
          #[inline]
          fn index(self, slice: &str) -> &Self::Output {
          #[inline]
          fn index_mut(self, slice: &mut str) -> &mut Self::Output {
              if slice.is_char_boundary(self.start) {
 -                // SAFETY: just checked that `start` is on a char boundary.
 -                unsafe { self.get_unchecked_mut(slice) }
 +                // SAFETY: just checked that `start` is on a char boundary,
 +                // and we are passing in a safe reference, so the return value will also be one.
 +                unsafe { &mut *self.get_unchecked_mut(slice) }
              } else {
                  super::slice_error_fail(slice, self.start, slice.len())
              }
      /// to the ending byte offset of a character (`end + 1` is either a starting
      /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`.
      #[stable(feature = "inclusive_range", since = "1.26.0")]
 -    impl SliceIndex<str> for ops::RangeInclusive<usize> {
 +    unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
          type Output = str;
          #[inline]
          fn get(self, slice: &str) -> Option<&Self::Output> {
              }
          }
          #[inline]
 -        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
 +        unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
              // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
              unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
          }
          #[inline]
 -        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
 +        unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
              // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
              unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
          }
      /// (`end + 1` is either a starting byte offset as defined by
      /// `is_char_boundary`, or equal to `len`), or if `end >= len`.
      #[stable(feature = "inclusive_range", since = "1.26.0")]
 -    impl SliceIndex<str> for ops::RangeToInclusive<usize> {
 +    unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> {
          type Output = str;
          #[inline]
          fn get(self, slice: &str) -> Option<&Self::Output> {
              if self.end == usize::MAX { None } else { (..self.end + 1).get_mut(slice) }
          }
          #[inline]
 -        unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
 +        unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
              // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
              unsafe { (..self.end + 1).get_unchecked(slice) }
          }
          #[inline]
 -        unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
 +        unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
              // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
              unsafe { (..self.end + 1).get_unchecked_mut(slice) }
          }
@@@ -2374,11 -2384,14 +2374,14 @@@ impl str 
          unsafe { Slices { str: self }.slice }
      }
  
-     /// Converts a mutable string slice to a mutable byte slice. To convert the
-     /// mutable byte slice back into a mutable string slice, use the
-     /// [`str::from_utf8_mut`] function.
+     /// Converts a mutable string slice to a mutable byte slice.
      ///
-     /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html
+     /// # Safety
+     ///
+     /// The caller must ensure that the content of the slice is valid UTF-8
+     /// before the borrow ends and the underlying `str` is used.
+     ///
+     /// Use of a `str` whose contents are not valid UTF-8 is undefined behavior.
      ///
      /// # Examples
      ///
      #[stable(feature = "str_checked_slicing", since = "1.20.0")]
      #[inline]
      pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
 -        // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
 -        unsafe { i.get_unchecked(self) }
 +        // SAFETY: the caller must uphold the safety contract for `get_unchecked`;
 +        // the slice is dereferencable because `self` is a safe reference.
 +        // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
 +        unsafe { &*i.get_unchecked(self) }
      }
  
      /// Returns a mutable, unchecked subslice of `str`.
      #[stable(feature = "str_checked_slicing", since = "1.20.0")]
      #[inline]
      pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
 -        // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
 -        unsafe { i.get_unchecked_mut(self) }
 +        // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`;
 +        // the slice is dereferencable because `self` is a safe reference.
 +        // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
 +        unsafe { &mut *i.get_unchecked_mut(self) }
      }
  
      /// Creates a string slice from another string slice, bypassing safety
      #[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked(begin..end)` instead")]
      #[inline]
      pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
 -        // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
 -        unsafe { (begin..end).get_unchecked(self) }
 +        // SAFETY: the caller must uphold the safety contract for `get_unchecked`;
 +        // the slice is dereferencable because `self` is a safe reference.
 +        // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
 +        unsafe { &*(begin..end).get_unchecked(self) }
      }
  
      /// Creates a string slice from another string slice, bypassing safety
      #[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked_mut(begin..end)` instead")]
      #[inline]
      pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
 -        // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
 -        unsafe { (begin..end).get_unchecked_mut(self) }
 +        // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`;
 +        // the slice is dereferencable because `self` is a safe reference.
 +        // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
 +        unsafe { &mut *(begin..end).get_unchecked_mut(self) }
      }
  
      /// Divide one string slice into two at an index.
      /// Simple patterns:
      ///
      /// ```
 -    /// let s = "Löwe 老虎 Léopard";
 +    /// let s = "Löwe 老虎 Léopard Gepardi";
      ///
      /// assert_eq!(s.find('L'), Some(0));
      /// assert_eq!(s.find('é'), Some(14));
 -    /// assert_eq!(s.find("Léopard"), Some(13));
 +    /// assert_eq!(s.find("pard"), Some(17));
      /// ```
      ///
      /// More complex patterns using point-free style and closures:
          pat.into_searcher(self).next_match().map(|(i, _)| i)
      }
  
 -    /// Returns the byte index of the last character of this string slice that
 -    /// matches the pattern.
 +    /// Returns the byte index for the first character of the rightmost match of the pattern in
 +    /// this string slice.
      ///
      /// Returns [`None`] if the pattern doesn't match.
      ///
      /// Simple patterns:
      ///
      /// ```
 -    /// let s = "Löwe 老虎 Léopard";
 +    /// let s = "Löwe 老虎 Léopard Gepardi";
      ///
      /// assert_eq!(s.rfind('L'), Some(13));
      /// assert_eq!(s.rfind('é'), Some(14));
 +    /// assert_eq!(s.rfind("pard"), Some(24));
      /// ```
      ///
      /// More complex patterns with closures:
          // We can treat each byte as character here: all multibyte characters
          // start with a byte that is not in the ascii range, so we will stop
          // there already.
 -        self.bytes().all(|b| b.is_ascii())
 +        self.as_bytes().is_ascii()
      }
  
      /// Checks that two strings are an ASCII case-insensitive match.