From 55beec2563276caa3793072a211d8cbb86cea75b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 4 Nov 2018 17:15:34 -0800 Subject: [PATCH 1/3] Use SliceIndex for str's Index/IndexMut impls This was missed by accident when the initial implementation landed! Closes #55603 --- src/libcore/str/mod.rs | 190 +++-------------------------------------- 1 file changed, 13 insertions(+), 177 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a2782dd8e2e43..b40b917c8f572 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1630,190 +1630,26 @@ mod traits { } } - /// 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> for str { - type Output = str; - #[inline] - fn index(&self, index: ops::Range) -> &str { - 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> for str { - #[inline] - fn index_mut(&mut self, index: ops::Range) -> &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> for str { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeTo) -> &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> for str { - #[inline] - fn index_mut(&mut self, index: ops::RangeTo) -> &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> for str { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeFrom) -> &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> for str { - #[inline] - fn index_mut(&mut self, index: ops::RangeFrom) -> &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 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 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> for str { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeInclusive) -> &str { - index.index(self) - } - } - - #[stable(feature = "inclusive_range", since = "1.26.0")] - impl ops::Index> for str { - type Output = str; + #[stable(feature = "str_slice_index", since = "1.32.0")] + impl ops::Index for str + where + T: SliceIndex + { + type Output = T::Output; #[inline] - fn index(&self, index: ops::RangeToInclusive) -> &str { + fn index(&self, index: T) -> &T::Output { index.index(self) } } - #[stable(feature = "inclusive_range", since = "1.26.0")] - impl ops::IndexMut> for str { - #[inline] - fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { - index.index_mut(self) - } - } - #[stable(feature = "inclusive_range", since = "1.26.0")] - impl ops::IndexMut> for str { + #[stable(feature = "str_slice_index", since = "1.32.0")] + impl ops::IndexMut for str + where + T: SliceIndex + { #[inline] - fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { + fn index_mut(&mut self, index: T) -> &mut T::Output { index.index_mut(self) } } From 5492963b1d3a3ca14e457f84a156c58437dc5d4a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 6 Nov 2018 21:10:34 -0800 Subject: [PATCH 2/3] Remove custom unimplemented message for SliceIndex This is unfortunate but since the trait is used by both slices and strings it was already inaccurate. --- src/libcore/slice/mod.rs | 3 --- src/test/ui/index-help.stderr | 3 +-- src/test/ui/indexing-requires-a-uint.stderr | 3 +-- src/test/ui/integral-indexing.stderr | 24 +++++++------------ .../ui/on-unimplemented/slice-index.stderr | 9 +++---- src/test/ui/str/str-idx.rs | 2 +- src/test/ui/str/str-idx.stderr | 14 +++++++---- src/test/ui/str/str-mut-idx.rs | 2 +- src/test/ui/str/str-mut-idx.stderr | 8 ++++--- 9 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8a6b212020b4e..f78cc9a22cd35 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2305,7 +2305,6 @@ impl [u8] { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"] impl ops::Index for [T] where I: SliceIndex<[T]> { @@ -2318,7 +2317,6 @@ impl ops::Index for [T] } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut for [T] where I: SliceIndex<[T]> { @@ -2369,7 +2367,6 @@ mod private_slice_index { /// 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`"] pub trait SliceIndex: private_slice_index::Sealed { /// The output type returned by methods. #[stable(feature = "slice_get_slice", since = "1.28.0")] diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index 669c0837fdabd..b3d92ed2f2ac0 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr @@ -2,9 +2,8 @@ error[E0277]: the trait bound `i32: std::slice::SliceIndex<[{integer}]>` is not --> $DIR/index-help.rs:13:5 | LL | x[0i32]; //~ ERROR E0277 - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^ the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i32` | - = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i32` = note: required because of the requirements on the impl of `std::ops::Index` for `std::vec::Vec<{integer}>` error: aborting due to previous error diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr index e9608e0b23519..e7cfdbab7e3cc 100644 --- a/src/test/ui/indexing-requires-a-uint.stderr +++ b/src/test/ui/indexing-requires-a-uint.stderr @@ -2,9 +2,8 @@ error[E0277]: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not s --> $DIR/indexing-requires-a-uint.rs:16:5 | LL | [0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied - | ^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^^ the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `u8` | - = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `u8` = note: required because of the requirements on the impl of `std::ops::Index` for `[{integer}]` error[E0308]: mismatched types diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr index d86421a79856f..ed4b157829a75 100644 --- a/src/test/ui/integral-indexing.stderr +++ b/src/test/ui/integral-indexing.stderr @@ -2,72 +2,64 @@ error[E0277]: the trait bound `u8: std::slice::SliceIndex<[isize]>` is not satis --> $DIR/integral-indexing.rs:16:5 | LL | v[3u8]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied - | ^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^ the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u8` | - = 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` for `std::vec::Vec` error[E0277]: the trait bound `i8: std::slice::SliceIndex<[isize]>` is not satisfied --> $DIR/integral-indexing.rs:17:5 | LL | v[3i8]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied - | ^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^ the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i8` | - = 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` for `std::vec::Vec` error[E0277]: the trait bound `u32: std::slice::SliceIndex<[isize]>` is not satisfied --> $DIR/integral-indexing.rs:18:5 | LL | v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^ the trait `std::slice::SliceIndex<[isize]>` is not implemented for `u32` | - = 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` for `std::vec::Vec` error[E0277]: the trait bound `i32: std::slice::SliceIndex<[isize]>` is not satisfied --> $DIR/integral-indexing.rs:19:5 | LL | v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^ the trait `std::slice::SliceIndex<[isize]>` is not implemented for `i32` | - = 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` for `std::vec::Vec` error[E0277]: the trait bound `u8: std::slice::SliceIndex<[u8]>` is not satisfied --> $DIR/integral-indexing.rs:22:5 | LL | s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied - | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^^^^^^^^^^^ the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u8` | - = 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` for `[u8]` error[E0277]: the trait bound `i8: std::slice::SliceIndex<[u8]>` is not satisfied --> $DIR/integral-indexing.rs:23:5 | LL | s.as_bytes()[3i8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied - | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^^^^^^^^^^^ the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i8` | - = 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` for `[u8]` error[E0277]: the trait bound `u32: std::slice::SliceIndex<[u8]>` is not satisfied --> $DIR/integral-indexing.rs:24:5 | LL | s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied - | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^^^^^^^^^^^^ the trait `std::slice::SliceIndex<[u8]>` is not implemented for `u32` | - = 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` for `[u8]` error[E0277]: the trait bound `i32: std::slice::SliceIndex<[u8]>` is not satisfied --> $DIR/integral-indexing.rs:25:5 | LL | s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied - | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^^^^^^^^^^^^ the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i32` | - = help: the trait `std::slice::SliceIndex<[u8]>` is not implemented for `i32` = note: required because of the requirements on the impl of `std::ops::Index` for `[u8]` error: aborting due to 8 previous errors diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index 6a4756eb1c98e..112b05d4b9908 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -2,18 +2,19 @@ error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisf --> $DIR/slice-index.rs:21:5 | LL | x[1i32]; //~ ERROR E0277 - | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^ the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32` | - = 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` for `[i32]` error[E0277]: the trait bound `std::ops::RangeTo: std::slice::SliceIndex<[i32]>` is not satisfied --> $DIR/slice-index.rs:22:5 | LL | x[..1i32]; //~ ERROR E0277 - | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | ^^^^^^^^^ the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo` | - = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo` + = help: the following implementations were found: + as std::slice::SliceIndex<[T]>> + as std::slice::SliceIndex> = note: required because of the requirements on the impl of `std::ops::Index>` for `[i32]` error: aborting due to 2 previous errors diff --git a/src/test/ui/str/str-idx.rs b/src/test/ui/str/str-idx.rs index b5f1ffb977ed6..9a3db4c4e0835 100644 --- a/src/test/ui/str/str-idx.rs +++ b/src/test/ui/str/str-idx.rs @@ -10,5 +10,5 @@ pub fn main() { let s: &str = "hello"; - let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}` + let c: u8 = s[4]; //~ ERROR the trait bound `{integer}: std::slice::SliceIndex` is not satisfied } diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 496187c92f187..7c43a3233e3cb 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -1,10 +1,16 @@ -error[E0277]: the type `str` cannot be indexed by `{integer}` +error[E0277]: the trait bound `{integer}: std::slice::SliceIndex` is not satisfied --> $DIR/str-idx.rs:13:17 | -LL | let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}` - | ^^^^ `str` cannot be indexed by `{integer}` +LL | let c: u8 = s[4]; //~ ERROR the trait bound `{integer}: std::slice::SliceIndex` is not satisfied + | ^^^^ the trait `std::slice::SliceIndex` is not implemented for `{integer}` | - = help: the trait `std::ops::Index<{integer}>` is not implemented for `str` + = help: the following implementations were found: + as std::slice::SliceIndex<[T]>> + as std::slice::SliceIndex> + as std::slice::SliceIndex<[T]>> + as std::slice::SliceIndex> + and 9 others + = note: required because of the requirements on the impl of `std::ops::Index<{integer}>` for `str` error: aborting due to previous error diff --git a/src/test/ui/str/str-mut-idx.rs b/src/test/ui/str/str-mut-idx.rs index 136bfaefa71c6..996f255b6d346 100644 --- a/src/test/ui/str/str-mut-idx.rs +++ b/src/test/ui/str/str-mut-idx.rs @@ -15,7 +15,7 @@ fn mutate(s: &mut str) { //~^ 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 trait bound `usize: std::slice::SliceIndex` is not satisfied } pub fn main() {} diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index df21ea2b274b6..db59fd6aef334 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -22,13 +22,15 @@ LL | s[1..2] = bot(); = note: to learn more, visit = 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 trait bound `usize: std::slice::SliceIndex` is not satisfied --> $DIR/str-mut-idx.rs:17:5 | LL | s[1usize] = bot(); - | ^^^^^^^^^ `str` cannot be mutably indexed by `usize` + | ^^^^^^^^^ the trait `std::slice::SliceIndex` is not implemented for `usize` | - = help: the trait `std::ops::IndexMut` is not implemented for `str` + = help: the following implementations were found: + > + = note: required because of the requirements on the impl of `std::ops::Index` for `str` error: aborting due to 3 previous errors From c2024ca8373a1ad586965e0e7fc70fcc9673dce8 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 6 Nov 2018 22:06:14 -0800 Subject: [PATCH 3/3] tidy --- src/test/ui/str/str-idx.rs | 2 +- src/test/ui/str/str-idx.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/str/str-idx.rs b/src/test/ui/str/str-idx.rs index 9a3db4c4e0835..0e661e66420cf 100644 --- a/src/test/ui/str/str-idx.rs +++ b/src/test/ui/str/str-idx.rs @@ -10,5 +10,5 @@ pub fn main() { let s: &str = "hello"; - let c: u8 = s[4]; //~ ERROR the trait bound `{integer}: std::slice::SliceIndex` is not satisfied + let c: u8 = s[4]; //~ ERROR the trait bound `{integer}: std::slice::SliceIndex` } diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 7c43a3233e3cb..7464ef9f03f13 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -1,7 +1,7 @@ error[E0277]: the trait bound `{integer}: std::slice::SliceIndex` is not satisfied --> $DIR/str-idx.rs:13:17 | -LL | let c: u8 = s[4]; //~ ERROR the trait bound `{integer}: std::slice::SliceIndex` is not satisfied +LL | let c: u8 = s[4]; //~ ERROR the trait bound `{integer}: std::slice::SliceIndex` | ^^^^ the trait `std::slice::SliceIndex` is not implemented for `{integer}` | = help: the following implementations were found: