Rollup merge of #57604 - alercah:str-index, r=sfackler

Make `str` indexing generic on `SliceIndex`.

Fixes #55603
diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs
index 6cfa367..d4ed861 100644
--- a/src/libcore/ops/index.rs
+++ b/src/libcore/ops/index.rs
@@ -51,21 +51,6 @@
 /// ```
 #[lang = "index"]
 #[rustc_on_unimplemented(
-    on(
-        _Self="&str",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
-    on(
-        _Self="str",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
-    on(
-        _Self="std::string::String",
-        note="you can use `.chars().nth()` or `.bytes().nth()`
-see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
-    ),
     message="the type `{Self}` cannot be indexed by `{Idx}`",
     label="`{Self}` cannot be indexed by `{Idx}`",
 )]
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index df4d97e..9f9515e 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2383,7 +2383,6 @@
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::Index<I> for [T]
     where I: SliceIndex<[T]>
 {
@@ -2396,7 +2395,6 @@
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::IndexMut<I> for [T]
     where I: SliceIndex<[T]>
 {
@@ -2447,7 +2445,19 @@
 
 /// A helper trait used for indexing operations.
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
-#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
+#[rustc_on_unimplemented(
+    on(
+        T = "str",
+        label = "string indices are ranges of `usize`",
+    ),
+    on(
+        all(any(T = "str", T = "&str", T = "std::string::String"), _Self="{integer}"),
+        note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+    ),
+    message = "the type `{T}` cannot be indexed by `{Self}`",
+    label = "slice indices are of type `usize` or ranges of `usize`",
+)]
 pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     /// The output type returned by methods.
     #[stable(feature = "slice_get_slice", since = "1.28.0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index bdde187..1ee8b77 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1621,190 +1621,26 @@
         }
     }
 
-    /// Implements substring slicing with syntax `&self[begin .. end]`.
-    ///
-    /// Returns a slice of the given string from the byte range
-    /// [`begin`..`end`).
-    ///
-    /// This operation is `O(1)`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `begin` or `end` does not point to the starting
-    /// byte offset of a character (as defined by `is_char_boundary`).
-    /// Requires that `begin <= end` and `end <= len` where `len` is the
-    /// length of the string.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// assert_eq!(&s[0 .. 1], "L");
-    ///
-    /// assert_eq!(&s[1 .. 9], "öwe 老");
-    ///
-    /// // these will panic:
-    /// // byte 2 lies within `ö`:
-    /// // &s[2 ..3];
-    ///
-    /// // byte 8 lies within `老`
-    /// // &s[1 .. 8];
-    ///
-    /// // byte 100 is outside the string
-    /// // &s[3 .. 100];
-    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::Range<usize>> for str {
-        type Output = str;
+    impl<I> ops::Index<I> for str
+    where
+        I: SliceIndex<str>,
+    {
+        type Output = I::Output;
+
         #[inline]
-        fn index(&self, index: ops::Range<usize>) -> &str {
+        fn index(&self, index: I) -> &I::Output {
             index.index(self)
         }
     }
 
-    /// Implements mutable substring slicing with syntax
-    /// `&mut self[begin .. end]`.
-    ///
-    /// Returns a mutable slice of the given string from the byte range
-    /// [`begin`..`end`).
-    ///
-    /// This operation is `O(1)`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `begin` or `end` does not point to the starting
-    /// byte offset of a character (as defined by `is_char_boundary`).
-    /// Requires that `begin <= end` and `end <= len` where `len` is the
-    /// length of the string.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::Range<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[.. end]`.
-    ///
-    /// Returns a slice of the string from the beginning to byte offset
-    /// `end`.
-    ///
-    /// Equivalent to `&self[0 .. end]`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeTo<usize>> for str {
-        type Output = str;
-
+    impl<I> ops::IndexMut<I> for str
+    where
+        I: SliceIndex<str>,
+    {
         #[inline]
-        fn index(&self, index: ops::RangeTo<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[.. end]`.
-    ///
-    /// Returns a mutable slice of the string from the beginning to byte offset
-    /// `end`.
-    ///
-    /// Equivalent to `&mut self[0 .. end]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeTo<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[begin ..]`.
-    ///
-    /// Returns a slice of the string from byte offset `begin`
-    /// to the end of the string.
-    ///
-    /// Equivalent to `&self[begin .. len]`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeFrom<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeFrom<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[begin ..]`.
-    ///
-    /// Returns a mutable slice of the string from byte offset `begin`
-    /// to the end of the string.
-    ///
-    /// Equivalent to `&mut self[begin .. len]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeFrom<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-
-    /// Implements substring slicing with syntax `&self[..]`.
-    ///
-    /// Returns a slice of the whole string. This operation can
-    /// never panic.
-    ///
-    /// Equivalent to `&self[0 .. len]`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ops::Index<ops::RangeFull> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, _index: ops::RangeFull) -> &str {
-            self
-        }
-    }
-
-    /// Implements mutable substring slicing with syntax `&mut self[..]`.
-    ///
-    /// Returns a mutable slice of the whole string. This operation can
-    /// never panic.
-    ///
-    /// Equivalent to `&mut self[0 .. len]`.
-    #[stable(feature = "derefmut_for_string", since = "1.3.0")]
-    impl ops::IndexMut<ops::RangeFull> for str {
-        #[inline]
-        fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
-            self
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::Index<ops::RangeInclusive<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::Index<ops::RangeToInclusive<usize>> for str {
-        type Output = str;
-
-        #[inline]
-        fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
-            index.index(self)
-        }
-    }
-
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::IndexMut<ops::RangeInclusive<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
-            index.index_mut(self)
-        }
-    }
-    #[stable(feature = "inclusive_range", since = "1.26.0")]
-    impl ops::IndexMut<ops::RangeToInclusive<usize>> for str {
-        #[inline]
-        fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
+        fn index_mut(&mut self, index: I) -> &mut I::Output {
             index.index_mut(self)
         }
     }
@@ -1815,6 +1651,18 @@
         panic!("attempted to index str up to maximum usize");
     }
 
+    /// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`.
+    ///
+    /// Returns a slice of the whole string, i.e., returns `&self` or `&mut
+    /// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike
+    /// other indexing operations, this can never panic.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// 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 {
         type Output = str;
@@ -1844,6 +1692,41 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin .. end]` or `&mut
+    /// self[begin .. end]`.
+    ///
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`, `end`).
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` or `end` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), if `begin > end`, or if
+    /// `end > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert_eq!(&s[0 .. 1], "L");
+    ///
+    /// assert_eq!(&s[1 .. 9], "öwe 老");
+    ///
+    /// // these will panic:
+    /// // byte 2 lies within `ö`:
+    /// // &s[2 ..3];
+    ///
+    /// // byte 8 lies within `老`
+    /// // &s[1 .. 8];
+    ///
+    /// // byte 100 is outside the string
+    /// // &s[3 .. 100];
+    /// ```
     #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     impl SliceIndex<str> for ops::Range<usize> {
         type Output = str;
@@ -1898,6 +1781,21 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[.. end]` or `&mut
+    /// self[.. end]`.
+    ///
+    /// Returns a slice of the given string from the byte range [`0`, `end`).
+    /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// 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> {
         type Output = str;
@@ -1943,6 +1841,22 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin ..]` or `&mut
+    /// self[begin ..]`.
+    ///
+    /// Returns a slice of the given string from the byte range [`begin`,
+    /// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin ..
+    /// len]`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Prior to 1.20.0, these indexing operations were still supported by
+    /// direct implementation of `Index` and `IndexMut`.
+    ///
+    /// # Panics
+    ///
+    /// 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> {
         type Output = str;
@@ -1990,6 +1904,22 @@
         }
     }
 
+    /// Implements substring slicing with syntax `&self[begin ..= end]` or `&mut
+    /// self[begin ..= end]`.
+    ///
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`, `end`]. Equivalent to `&self [begin .. end + 1]` or `&mut
+    /// self[begin .. end + 1]`, except if `end` has the maximum value for
+    /// `usize`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `begin` does not point to the starting byte offset of
+    /// a character (as defined by `is_char_boundary`), if `end` does not point
+    /// 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> {
         type Output = str;
@@ -2023,8 +1953,20 @@
         }
     }
 
-
-
+    /// Implements substring slicing with syntax `&self[..= end]` or `&mut
+    /// self[..= end]`.
+    ///
+    /// Returns a slice of the given string from the byte range [0, `end`].
+    /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
+    /// value for `usize`.
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `end` does not point to the ending byte offset of a character
+    /// (`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> {
         type Output = str;
diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr
index c8b23d8..4c585a9 100644
--- a/src/test/ui/index-help.stderr
+++ b/src/test/ui/index-help.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[{integer}]>` is not satisfied
+error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
   --> $DIR/index-help.rs:3:5
    |
 LL |     x[0i32]; //~ ERROR E0277
diff --git a/src/test/ui/indexing-requires-a-uint.rs b/src/test/ui/indexing-requires-a-uint.rs
index 2db3c58..dbe9b44 100644
--- a/src/test/ui/indexing-requires-a-uint.rs
+++ b/src/test/ui/indexing-requires-a-uint.rs
@@ -3,7 +3,7 @@
 
 fn main() {
     fn bar<T>(_: T) {}
-    [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+    [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
 
     [0][0]; // should infer to be a usize
 
diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr
index 767f1af..363c3d0 100644
--- a/src/test/ui/indexing-requires-a-uint.stderr
+++ b/src/test/ui/indexing-requires-a-uint.stderr
@@ -1,7 +1,7 @@
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+error[E0277]: the type `[{integer}]` cannot be indexed by `u8`
   --> $DIR/indexing-requires-a-uint.rs:6:5
    |
-LL |     [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
+LL |     [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8`
    |     ^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `u8`
diff --git a/src/test/ui/integral-indexing.rs b/src/test/ui/integral-indexing.rs
index 7bdbc45..f076dfc 100644
--- a/src/test/ui/integral-indexing.rs
+++ b/src/test/ui/integral-indexing.rs
@@ -3,14 +3,14 @@
     let s: String = "abcdef".to_string();
     v[3_usize];
     v[3];
-    v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
-    v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+    v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
+    v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
+    v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
+    v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
     s.as_bytes()[3_usize];
     s.as_bytes()[3];
-    s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3i8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
-    s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+    s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
+    s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
+    s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
+    s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
 }
diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr
index 7f2dddc..efbad86 100644
--- a/src/test/ui/integral-indexing.stderr
+++ b/src/test/ui/integral-indexing.stderr
@@ -1,70 +1,70 @@
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:6:5
    |
-LL |     v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
    |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u8`
    = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `i8: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:7:5
    |
-LL |     v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
    |     ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i8`
    = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `u32: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:8:5
    |
-LL |     v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
    |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u32`
    = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[isize]>` is not satisfied
+error[E0277]: the type `[isize]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:9:5
    |
-LL |     v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+LL |     v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
    |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i32`
    = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<isize>`
 
-error[E0277]: the trait bound `u8: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:12:5
    |
-LL |     s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
    |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u8`
    = note: required because of the requirements on the impl of `std::ops::Index<u8>` for `[u8]`
 
-error[E0277]: the trait bound `i8: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:13:5
    |
-LL |     s.as_bytes()[3i8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
    |     ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i8`
    = note: required because of the requirements on the impl of `std::ops::Index<i8>` for `[u8]`
 
-error[E0277]: the trait bound `u32: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:14:5
    |
-LL |     s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
    |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u32`
    = note: required because of the requirements on the impl of `std::ops::Index<u32>` for `[u8]`
 
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[u8]>` is not satisfied
+error[E0277]: the type `[u8]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:15:5
    |
-LL |     s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
+LL |     s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
    |     ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i32`
diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr
index 3a32e13..7b45d84 100644
--- a/src/test/ui/on-unimplemented/slice-index.stderr
+++ b/src/test/ui/on-unimplemented/slice-index.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied
+error[E0277]: the type `[i32]` cannot be indexed by `i32`
   --> $DIR/slice-index.rs:11:5
    |
 LL |     x[1i32]; //~ ERROR E0277
@@ -7,7 +7,7 @@
    = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
    = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[i32]`
 
-error[E0277]: the trait bound `std::ops::RangeTo<i32>: std::slice::SliceIndex<[i32]>` is not satisfied
+error[E0277]: the type `[i32]` cannot be indexed by `std::ops::RangeTo<i32>`
   --> $DIR/slice-index.rs:12:5
    |
 LL |     x[..1i32]; //~ ERROR E0277
diff --git a/src/test/ui/str/str-idx.rs b/src/test/ui/str/str-idx.rs
index 2ea8049..1b32ed5 100644
--- a/src/test/ui/str/str-idx.rs
+++ b/src/test/ui/str/str-idx.rs
@@ -1,4 +1,7 @@
 pub fn main() {
     let s: &str = "hello";
-    let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+    let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
 }
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index 71b1747..99df85d 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -1,13 +1,43 @@
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:3:17
    |
-LL |     let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
-   |                 ^^^^ `str` cannot be indexed by `{integer}`
+LL |     let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |                 ^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `std::ops::Index<{integer}>` is not implemented for `str`
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+   = note: required because of the requirements on the impl of `std::ops::Index<{integer}>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:4:15
+   |
+LL |     let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |               ^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
-error: aborting due to previous error
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-idx.rs:5:15
+   |
+LL |     let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}`
+   |               ^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-idx.rs:6:17
+   |
+LL |     let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char`
+   |                 ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/str/str-mut-idx.rs b/src/test/ui/str/str-mut-idx.rs
index cebbbc3..575a9ea 100644
--- a/src/test/ui/str/str-mut-idx.rs
+++ b/src/test/ui/str/str-mut-idx.rs
@@ -5,7 +5,13 @@
     //~^ ERROR the size for values of type
     //~| ERROR the size for values of type
     s[1usize] = bot();
-    //~^ ERROR the type `str` cannot be mutably indexed by `usize`
+    //~^ ERROR the type `str` cannot be indexed by `usize`
+    s.get_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s.get_unchecked_mut(1);
+    //~^ ERROR the type `str` cannot be indexed by `{integer}`
+    s['c'];
+    //~^ ERROR the type `str` cannot be indexed by `char`
 }
 
 pub fn main() {}
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index a1212c5..beb2272 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -22,16 +22,44 @@
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: the left-hand-side of an assignment must have a statically known size
 
-error[E0277]: the type `str` cannot be mutably indexed by `usize`
+error[E0277]: the type `str` cannot be indexed by `usize`
   --> $DIR/str-mut-idx.rs:7:5
    |
 LL |     s[1usize] = bot();
-   |     ^^^^^^^^^ `str` cannot be mutably indexed by `usize`
+   |     ^^^^^^^^^ string indices are ranges of `usize`
    |
-   = help: the trait `std::ops::IndexMut<usize>` is not implemented for `str`
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `usize`
+   = note: required because of the requirements on the impl of `std::ops::Index<usize>` for `str`
+
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:9:7
+   |
+LL |     s.get_mut(1);
+   |       ^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
 
-error: aborting due to 3 previous errors
+error[E0277]: the type `str` cannot be indexed by `{integer}`
+  --> $DIR/str-mut-idx.rs:11:7
+   |
+LL |     s.get_unchecked_mut(1);
+   |       ^^^^^^^^^^^^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `{integer}`
+   = note: you can use `.chars().nth()` or `.bytes().nth()`
+           see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
+
+error[E0277]: the type `str` cannot be indexed by `char`
+  --> $DIR/str-mut-idx.rs:13:5
+   |
+LL |     s['c'];
+   |     ^^^^^^ string indices are ranges of `usize`
+   |
+   = help: the trait `std::slice::SliceIndex<str>` is not implemented for `char`
+   = note: required because of the requirements on the impl of `std::ops::Index<char>` for `str`
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0277`.