diff --git a/library/core/src/bstr.rs b/library/core/src/bstr/mod.rs
similarity index 54%
rename from library/core/src/bstr.rs
rename to library/core/src/bstr/mod.rs
index ae84fd8adb61c..c8d0c701ba8b7 100644
--- a/library/core/src/bstr.rs
+++ b/library/core/src/bstr/mod.rs
@@ -1,12 +1,13 @@
 //! The `ByteStr` type and trait implementations.
 
+mod traits;
+
+#[unstable(feature = "bstr_internals", issue = "none")]
+pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
+
 use crate::borrow::{Borrow, BorrowMut};
-use crate::cmp::Ordering;
-use crate::ops::{
-    Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive,
-    RangeTo, RangeToInclusive,
-};
-use crate::{fmt, hash};
+use crate::fmt;
+use crate::ops::{Deref, DerefMut, DerefPure};
 
 /// A wrapper for `&[u8]` representing a human-readable string that's conventionally, but not
 /// always, UTF-8.
@@ -91,6 +92,13 @@ impl ByteStr {
     pub fn as_bytes(&self) -> &[u8] {
         &self.0
     }
+
+    #[doc(hidden)]
+    #[unstable(feature = "bstr_internals", issue = "none")]
+    #[inline]
+    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
+        &mut self.0
+    }
 }
 
 #[unstable(feature = "bstr", issue = "134915")]
@@ -295,273 +303,6 @@ impl<'a> Default for &'a mut ByteStr {
 //     }
 // }
 
-#[unstable(feature = "bstr", issue = "134915")]
-impl hash::Hash for ByteStr {
-    #[inline]
-    fn hash<H: hash::Hasher>(&self, state: &mut H) {
-        self.0.hash(state);
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<usize> for ByteStr {
-    type Output = u8;
-
-    #[inline]
-    fn index(&self, idx: usize) -> &u8 {
-        &self.0[idx]
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<RangeFull> for ByteStr {
-    type Output = ByteStr;
-
-    #[inline]
-    fn index(&self, _: RangeFull) -> &ByteStr {
-        self
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<Range<usize>> for ByteStr {
-    type Output = ByteStr;
-
-    #[inline]
-    fn index(&self, r: Range<usize>) -> &ByteStr {
-        ByteStr::from_bytes(&self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<RangeInclusive<usize>> for ByteStr {
-    type Output = ByteStr;
-
-    #[inline]
-    fn index(&self, r: RangeInclusive<usize>) -> &ByteStr {
-        ByteStr::from_bytes(&self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<RangeFrom<usize>> for ByteStr {
-    type Output = ByteStr;
-
-    #[inline]
-    fn index(&self, r: RangeFrom<usize>) -> &ByteStr {
-        ByteStr::from_bytes(&self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<RangeTo<usize>> for ByteStr {
-    type Output = ByteStr;
-
-    #[inline]
-    fn index(&self, r: RangeTo<usize>) -> &ByteStr {
-        ByteStr::from_bytes(&self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Index<RangeToInclusive<usize>> for ByteStr {
-    type Output = ByteStr;
-
-    #[inline]
-    fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr {
-        ByteStr::from_bytes(&self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<usize> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, idx: usize) -> &mut u8 {
-        &mut self.0[idx]
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<RangeFull> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr {
-        self
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<Range<usize>> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr {
-        ByteStr::from_bytes_mut(&mut self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<RangeInclusive<usize>> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr {
-        ByteStr::from_bytes_mut(&mut self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<RangeFrom<usize>> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr {
-        ByteStr::from_bytes_mut(&mut self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<RangeTo<usize>> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr {
-        ByteStr::from_bytes_mut(&mut self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl IndexMut<RangeToInclusive<usize>> for ByteStr {
-    #[inline]
-    fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr {
-        ByteStr::from_bytes_mut(&mut self.0[r])
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Eq for ByteStr {}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl PartialEq<ByteStr> for ByteStr {
-    #[inline]
-    fn eq(&self, other: &ByteStr) -> bool {
-        &self.0 == &other.0
-    }
-}
-
-#[doc(hidden)]
-#[macro_export]
-#[unstable(feature = "bstr_internals", issue = "none")]
-macro_rules! impl_partial_eq {
-    ($lhs:ty, $rhs:ty) => {
-        #[allow(unused_lifetimes)]
-        impl<'a> PartialEq<$rhs> for $lhs {
-            #[inline]
-            fn eq(&self, other: &$rhs) -> bool {
-                let other: &[u8] = other.as_ref();
-                PartialEq::eq(self.as_bytes(), other)
-            }
-        }
-
-        #[allow(unused_lifetimes)]
-        impl<'a> PartialEq<$lhs> for $rhs {
-            #[inline]
-            fn eq(&self, other: &$lhs) -> bool {
-                let this: &[u8] = self.as_ref();
-                PartialEq::eq(this, other.as_bytes())
-            }
-        }
-    };
-}
-
-#[doc(hidden)]
-#[unstable(feature = "bstr_internals", issue = "none")]
-pub use impl_partial_eq;
-
-#[doc(hidden)]
-#[macro_export]
-#[unstable(feature = "bstr_internals", issue = "none")]
-macro_rules! impl_partial_eq_ord {
-    ($lhs:ty, $rhs:ty) => {
-        $crate::bstr::impl_partial_eq!($lhs, $rhs);
-
-        #[allow(unused_lifetimes)]
-        #[unstable(feature = "bstr", issue = "134915")]
-        impl<'a> PartialOrd<$rhs> for $lhs {
-            #[inline]
-            fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
-                let other: &[u8] = other.as_ref();
-                PartialOrd::partial_cmp(self.as_bytes(), other)
-            }
-        }
-
-        #[allow(unused_lifetimes)]
-        #[unstable(feature = "bstr", issue = "134915")]
-        impl<'a> PartialOrd<$lhs> for $rhs {
-            #[inline]
-            fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
-                let this: &[u8] = self.as_ref();
-                PartialOrd::partial_cmp(this, other.as_bytes())
-            }
-        }
-    };
-}
-
-#[doc(hidden)]
-#[unstable(feature = "bstr_internals", issue = "none")]
-pub use impl_partial_eq_ord;
-
-#[doc(hidden)]
-#[macro_export]
-#[unstable(feature = "bstr_internals", issue = "none")]
-macro_rules! impl_partial_eq_n {
-    ($lhs:ty, $rhs:ty) => {
-        #[allow(unused_lifetimes)]
-        #[unstable(feature = "bstr", issue = "134915")]
-        impl<const N: usize> PartialEq<$rhs> for $lhs {
-            #[inline]
-            fn eq(&self, other: &$rhs) -> bool {
-                let other: &[u8] = other.as_ref();
-                PartialEq::eq(self.as_bytes(), other)
-            }
-        }
-
-        #[allow(unused_lifetimes)]
-        #[unstable(feature = "bstr", issue = "134915")]
-        impl<const N: usize> PartialEq<$lhs> for $rhs {
-            #[inline]
-            fn eq(&self, other: &$lhs) -> bool {
-                let this: &[u8] = self.as_ref();
-                PartialEq::eq(this, other.as_bytes())
-            }
-        }
-    };
-}
-
-#[doc(hidden)]
-#[unstable(feature = "bstr_internals", issue = "none")]
-pub use impl_partial_eq_n;
-
-// PartialOrd with `[u8]` omitted to avoid inference failures
-impl_partial_eq!(ByteStr, [u8]);
-// PartialOrd with `&[u8]` omitted to avoid inference failures
-impl_partial_eq!(ByteStr, &[u8]);
-// PartialOrd with `str` omitted to avoid inference failures
-impl_partial_eq!(ByteStr, str);
-// PartialOrd with `&str` omitted to avoid inference failures
-impl_partial_eq!(ByteStr, &str);
-// PartialOrd with `[u8; N]` omitted to avoid inference failures
-impl_partial_eq_n!(ByteStr, [u8; N]);
-// PartialOrd with `[u8; N]` omitted to avoid inference failures
-impl_partial_eq_n!(ByteStr, &[u8; N]);
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl Ord for ByteStr {
-    #[inline]
-    fn cmp(&self, other: &ByteStr) -> Ordering {
-        Ord::cmp(&self.0, &other.0)
-    }
-}
-
-#[unstable(feature = "bstr", issue = "134915")]
-impl PartialOrd for ByteStr {
-    #[inline]
-    fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> {
-        PartialOrd::partial_cmp(&self.0, &other.0)
-    }
-}
-
 #[unstable(feature = "bstr", issue = "134915")]
 impl<'a> TryFrom<&'a ByteStr> for &'a str {
     type Error = crate::str::Utf8Error;
diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs
new file mode 100644
index 0000000000000..ff46bb13ba4eb
--- /dev/null
+++ b/library/core/src/bstr/traits.rs
@@ -0,0 +1,277 @@
+//! Trait implementations for `ByteStr`.
+
+use crate::bstr::ByteStr;
+use crate::cmp::Ordering;
+use crate::slice::SliceIndex;
+use crate::{hash, ops, range};
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl Ord for ByteStr {
+    #[inline]
+    fn cmp(&self, other: &ByteStr) -> Ordering {
+        Ord::cmp(&self.0, &other.0)
+    }
+}
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl PartialOrd for ByteStr {
+    #[inline]
+    fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&self.0, &other.0)
+    }
+}
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl PartialEq<ByteStr> for ByteStr {
+    #[inline]
+    fn eq(&self, other: &ByteStr) -> bool {
+        &self.0 == &other.0
+    }
+}
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl Eq for ByteStr {}
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl hash::Hash for ByteStr {
+    #[inline]
+    fn hash<H: hash::Hasher>(&self, state: &mut H) {
+        self.0.hash(state);
+    }
+}
+
+#[doc(hidden)]
+#[macro_export]
+#[unstable(feature = "bstr_internals", issue = "none")]
+macro_rules! impl_partial_eq {
+    ($lhs:ty, $rhs:ty) => {
+        #[allow(unused_lifetimes)]
+        impl<'a> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                let other: &[u8] = other.as_ref();
+                PartialEq::eq(self.as_bytes(), other)
+            }
+        }
+
+        #[allow(unused_lifetimes)]
+        impl<'a> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool {
+                let this: &[u8] = self.as_ref();
+                PartialEq::eq(this, other.as_bytes())
+            }
+        }
+    };
+}
+
+#[doc(hidden)]
+#[unstable(feature = "bstr_internals", issue = "none")]
+pub use impl_partial_eq;
+
+#[doc(hidden)]
+#[macro_export]
+#[unstable(feature = "bstr_internals", issue = "none")]
+macro_rules! impl_partial_eq_ord {
+    ($lhs:ty, $rhs:ty) => {
+        $crate::bstr::impl_partial_eq!($lhs, $rhs);
+
+        #[allow(unused_lifetimes)]
+        #[unstable(feature = "bstr", issue = "134915")]
+        impl<'a> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
+                let other: &[u8] = other.as_ref();
+                PartialOrd::partial_cmp(self.as_bytes(), other)
+            }
+        }
+
+        #[allow(unused_lifetimes)]
+        #[unstable(feature = "bstr", issue = "134915")]
+        impl<'a> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
+                let this: &[u8] = self.as_ref();
+                PartialOrd::partial_cmp(this, other.as_bytes())
+            }
+        }
+    };
+}
+
+#[doc(hidden)]
+#[unstable(feature = "bstr_internals", issue = "none")]
+pub use impl_partial_eq_ord;
+
+#[doc(hidden)]
+#[macro_export]
+#[unstable(feature = "bstr_internals", issue = "none")]
+macro_rules! impl_partial_eq_n {
+    ($lhs:ty, $rhs:ty) => {
+        #[allow(unused_lifetimes)]
+        #[unstable(feature = "bstr", issue = "134915")]
+        impl<const N: usize> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                let other: &[u8] = other.as_ref();
+                PartialEq::eq(self.as_bytes(), other)
+            }
+        }
+
+        #[allow(unused_lifetimes)]
+        #[unstable(feature = "bstr", issue = "134915")]
+        impl<const N: usize> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool {
+                let this: &[u8] = self.as_ref();
+                PartialEq::eq(this, other.as_bytes())
+            }
+        }
+    };
+}
+
+#[doc(hidden)]
+#[unstable(feature = "bstr_internals", issue = "none")]
+pub use impl_partial_eq_n;
+
+// PartialOrd with `[u8]` omitted to avoid inference failures
+impl_partial_eq!(ByteStr, [u8]);
+// PartialOrd with `&[u8]` omitted to avoid inference failures
+impl_partial_eq!(ByteStr, &[u8]);
+// PartialOrd with `str` omitted to avoid inference failures
+impl_partial_eq!(ByteStr, str);
+// PartialOrd with `&str` omitted to avoid inference failures
+impl_partial_eq!(ByteStr, &str);
+// PartialOrd with `[u8; N]` omitted to avoid inference failures
+impl_partial_eq_n!(ByteStr, [u8; N]);
+// PartialOrd with `[u8; N]` omitted to avoid inference failures
+impl_partial_eq_n!(ByteStr, &[u8; N]);
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl<I> ops::Index<I> for ByteStr
+where
+    I: SliceIndex<ByteStr>,
+{
+    type Output = I::Output;
+
+    #[inline]
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+#[unstable(feature = "bstr", issue = "134915")]
+impl<I> ops::IndexMut<I> for ByteStr
+where
+    I: SliceIndex<ByteStr>,
+{
+    #[inline]
+    fn index_mut(&mut self, index: I) -> &mut I::Output {
+        index.index_mut(self)
+    }
+}
+
+#[unstable(feature = "bstr", issue = "134915")]
+unsafe impl SliceIndex<ByteStr> for ops::RangeFull {
+    type Output = ByteStr;
+    #[inline]
+    fn get(self, slice: &ByteStr) -> Option<&Self::Output> {
+        Some(slice)
+    }
+    #[inline]
+    fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> {
+        Some(slice)
+    }
+    #[inline]
+    unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output {
+        slice
+    }
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output {
+        slice
+    }
+    #[inline]
+    fn index(self, slice: &ByteStr) -> &Self::Output {
+        slice
+    }
+    #[inline]
+    fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output {
+        slice
+    }
+}
+
+#[unstable(feature = "bstr", issue = "134915")]
+unsafe impl SliceIndex<ByteStr> for usize {
+    type Output = u8;
+    #[inline]
+    fn get(self, slice: &ByteStr) -> Option<&Self::Output> {
+        self.get(slice.as_bytes())
+    }
+    #[inline]
+    fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> {
+        self.get_mut(slice.as_bytes_mut())
+    }
+    #[inline]
+    unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output {
+        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
+        unsafe { self.get_unchecked(slice as *const [u8]) }
+    }
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output {
+        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
+        unsafe { self.get_unchecked_mut(slice as *mut [u8]) }
+    }
+    #[inline]
+    fn index(self, slice: &ByteStr) -> &Self::Output {
+        self.index(slice.as_bytes())
+    }
+    #[inline]
+    fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output {
+        self.index_mut(slice.as_bytes_mut())
+    }
+}
+
+macro_rules! impl_slice_index {
+    ($index:ty) => {
+        #[unstable(feature = "bstr", issue = "134915")]
+        unsafe impl SliceIndex<ByteStr> for $index {
+            type Output = ByteStr;
+            #[inline]
+            fn get(self, slice: &ByteStr) -> Option<&Self::Output> {
+                self.get(slice.as_bytes()).map(ByteStr::from_bytes)
+            }
+            #[inline]
+            fn get_mut(self, slice: &mut ByteStr) -> Option<&mut Self::Output> {
+                self.get_mut(slice.as_bytes_mut()).map(ByteStr::from_bytes_mut)
+            }
+            #[inline]
+            unsafe fn get_unchecked(self, slice: *const ByteStr) -> *const Self::Output {
+                // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
+                unsafe { self.get_unchecked(slice as *const [u8]) as *const ByteStr }
+            }
+            #[inline]
+            unsafe fn get_unchecked_mut(self, slice: *mut ByteStr) -> *mut Self::Output {
+                // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
+                unsafe { self.get_unchecked_mut(slice as *mut [u8]) as *mut ByteStr }
+            }
+            #[inline]
+            fn index(self, slice: &ByteStr) -> &Self::Output {
+                ByteStr::from_bytes(self.index(slice.as_bytes()))
+            }
+            #[inline]
+            fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output {
+                ByteStr::from_bytes_mut(self.index_mut(slice.as_bytes_mut()))
+            }
+        }
+    };
+}
+
+impl_slice_index!(ops::IndexRange);
+impl_slice_index!(ops::Range<usize>);
+impl_slice_index!(range::Range<usize>);
+impl_slice_index!(ops::RangeTo<usize>);
+impl_slice_index!(ops::RangeFrom<usize>);
+impl_slice_index!(range::RangeFrom<usize>);
+impl_slice_index!(ops::RangeInclusive<usize>);
+impl_slice_index!(range::RangeInclusive<usize>);
+impl_slice_index!(ops::RangeToInclusive<usize>);
+impl_slice_index!((ops::Bound<usize>, ops::Bound<usize>));
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index 1974e13eabcee..ac79e3f12bd03 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -5,8 +5,9 @@ LL |     x[0i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `i32`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index 5c60a30946d37..62a1ca3d0573c 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -5,8 +5,9 @@ LL |     [0][0u8];
    |         ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `u8`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[{integer}]` to implement `Index<u8>`
    = note: 1 redundant requirement hidden
    = note: required for `[{integer}; 1]` to implement `Index<u8>`
diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr
index e7a45c2c88dd9..26253e078cb40 100644
--- a/tests/ui/integral-indexing.stderr
+++ b/tests/ui/integral-indexing.stderr
@@ -5,8 +5,9 @@ LL |     v[3u8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `u8`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `Vec<isize>` to implement `Index<u8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i8`
@@ -16,8 +17,9 @@ LL |     v[3i8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `i8`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `Vec<isize>` to implement `Index<i8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `u32`
@@ -27,8 +29,9 @@ LL |     v[3u32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `u32`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `Vec<isize>` to implement `Index<u32>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i32`
@@ -38,8 +41,9 @@ LL |     v[3i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `i32`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `Vec<isize>` to implement `Index<i32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u8`
@@ -49,8 +53,9 @@ LL |     s.as_bytes()[3u8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `u8`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[u8]` to implement `Index<u8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i8`
@@ -60,8 +65,9 @@ LL |     s.as_bytes()[3i8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `i8`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[u8]` to implement `Index<i8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u32`
@@ -71,8 +77,9 @@ LL |     s.as_bytes()[3u32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `u32`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[u8]` to implement `Index<u32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i32`
@@ -82,8 +89,9 @@ LL |     s.as_bytes()[3i32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `i32`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[u8]` to implement `Index<i32>`
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index 0a9ebe3f088e0..e011826bc8f7b 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -5,8 +5,9 @@ LL |     x[1i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
-           but it is implemented for `usize`
-   = help: for that trait implementation, expected `usize`, found `i32`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[i32]` to implement `Index<i32>`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
@@ -17,6 +18,7 @@ LL |     x[..1i32];
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`
    = help: the following other types implement trait `SliceIndex<T>`:
+             `RangeTo<usize>` implements `SliceIndex<ByteStr>`
              `RangeTo<usize>` implements `SliceIndex<[T]>`
              `RangeTo<usize>` implements `SliceIndex<str>`
    = note: required for `[i32]` to implement `Index<RangeTo<i32>>`
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index bedbbd9cb5029..60cae7e84e373 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -4,11 +4,12 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
 LL |     let _: u8 = s[4];
    |                   ^ string indices are ranges of `usize`
    |
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
-           but trait `SliceIndex<[_]>` is implemented for `usize`
-   = help: for that trait implementation, expected `[_]`, found `str`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `str` to implement `Index<{integer}>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -19,11 +20,12 @@ LL |     let _ = s.get(4);
    |               |
    |               required by a bound introduced by this call
    |
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
-           but trait `SliceIndex<[_]>` is implemented for `usize`
-   = help: for that trait implementation, expected `[_]`, found `str`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -35,11 +37,12 @@ LL |     let _ = s.get_unchecked(4);
    |               |
    |               required by a bound introduced by this call
    |
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
-           but trait `SliceIndex<[_]>` is implemented for `usize`
-   = help: for that trait implementation, expected `[_]`, found `str`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index f09a4c329e5d8..4e3fe126ed838 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -31,8 +31,9 @@ LL |     s[1usize] = bot();
    |       ^^^^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
-           but trait `SliceIndex<[_]>` is implemented for it
-   = help: for that trait implementation, expected `[_]`, found `str`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `str` to implement `Index<usize>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -43,11 +44,12 @@ LL |     s.get_mut(1);
    |       |
    |       required by a bound introduced by this call
    |
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
-           but trait `SliceIndex<[_]>` is implemented for `usize`
-   = help: for that trait implementation, expected `[_]`, found `str`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -59,11 +61,12 @@ LL |     s.get_unchecked_mut(1);
    |       |
    |       required by a bound introduced by this call
    |
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
-           but trait `SliceIndex<[_]>` is implemented for `usize`
-   = help: for that trait implementation, expected `[_]`, found `str`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 0335d8eafde4b..937f32677a6c8 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -4,9 +4,10 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `&usize`
 LL |     let one_item_please: i32 = [1, 2, 3][i];
    |                                          ^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&_`
-           but it is implemented for `_`
-   = help: for that trait implementation, expected `usize`, found `&usize`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
+   = help: the following other types implement trait `SliceIndex<T>`:
+             `usize` implements `SliceIndex<ByteStr>`
+             `usize` implements `SliceIndex<[T]>`
    = note: required for `[{integer}]` to implement `Index<&usize>`
    = note: 1 redundant requirement hidden
    = note: required for `[{integer}; 3]` to implement `Index<&usize>`