diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 2f74ab5026e92..a3d38bdd1b31b 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1157,25 +1157,21 @@ impl str { core_str::StrExt::rmatches(self, pat) } - /// An iterator over the start and end indices of the disjoint matches - /// of a pattern within `self`. + /// An iterator over the disjoint matches of a pattern within `self` as well + /// as the index that the match starts at. /// /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the first - /// match are returned. + /// corresponding to the first match are returned. /// - /// The pattern can be a simple `&str`, `char`, or a closure that - /// determines if a character matches. - /// Additional libraries might provide more complex patterns like - /// regular expressions. + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// if a character matches. Additional libraries might provide more complex + /// patterns like regular expressions. /// /// # Iterator behavior /// /// The returned iterator will be double ended if the pattern allows a - /// reverse search - /// and forward/reverse search yields the same elements. This is true for, - /// eg, `char` but not - /// for `&str`. + /// reverse search and forward/reverse search yields the same elements. This + /// is true for, eg, `char` but not for `&str`. /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, `rmatch_indices()` can be used. @@ -1185,42 +1181,36 @@ impl str { /// ``` /// #![feature(str_match_indices)] /// - /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]); + /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); /// - /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, [(1, 4), (4, 7)]); + /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1, "abc"), (4, "abc")]); /// - /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, [(0, 3)]); // only the first `aba` + /// let v: Vec<_> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, "aba")]); // only the first `aba` /// ``` #[unstable(feature = "str_match_indices", reason = "might have its iterator type changed", issue = "27743")] - // NB: Right now MatchIndices yields `(usize, usize)`, but it would - // be more consistent with `matches` and `char_indices` to return `(usize, &str)` pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { core_str::StrExt::match_indices(self, pat) } - /// An iterator over the start and end indices of the disjoint matches of - /// a pattern within - /// `self`, yielded in reverse order. + /// An iterator over the disjoint matches of a pattern within `self`, + /// yielded in reverse order along with the index of the match. /// /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the last - /// match are returned. + /// corresponding to the last match are returned. /// - /// The pattern can be a simple `&str`, `char`, or a closure that - /// determines if a character matches. - /// Additional libraries might provide more complex patterns like - /// regular expressions. + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// if a character matches. Additional libraries might provide more complex + /// patterns like regular expressions. /// /// # Iterator behavior /// - /// The returned iterator requires that the pattern supports a - /// reverse search, - /// and it will be double ended if a forward/reverse search yields + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be double ended if a forward/reverse search yields /// the same elements. /// /// For iterating from the front, `match_indices()` can be used. @@ -1230,20 +1220,18 @@ impl str { /// ``` /// #![feature(str_match_indices)] /// - /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]); + /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); /// - /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(4, 7), (1, 4)]); + /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4, "abc"), (1, "abc")]); /// - /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect(); - /// assert_eq!(v, [(2, 5)]); // only the last `aba` + /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, "aba")]); // only the last `aba` /// ``` #[unstable(feature = "str_match_indices", reason = "might have its iterator type changed", issue = "27743")] - // NB: Right now RMatchIndices yields `(usize, usize)`, but it would - // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)` pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> where P::Searcher: ReverseSearcher<'a> { @@ -1416,10 +1404,10 @@ impl str { pub fn replace(&self, from: &str, to: &str) -> String { let mut result = String::new(); let mut last_end = 0; - for (start, end) in self.match_indices(from) { + for (start, part) in self.match_indices(from) { result.push_str(unsafe { self.slice_unchecked(last_end, start) }); result.push_str(to); - last_end = end; + last_end = start + part.len(); } result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); result diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 7b481f6399116..b4555679e9c1b 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -1047,7 +1047,7 @@ fn test_pattern_deref_forward() { fn test_empty_match_indices() { let data = "aä中!"; let vec: Vec<_> = data.match_indices("").collect(); - assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]); + assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]); } #[test] @@ -1477,7 +1477,7 @@ generate_iterator_test! { generate_iterator_test! { double_ended_match_indices { - ("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)]; + ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")]; } with str::match_indices, str::rmatch_indices; } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 69ebcb1ab7e14..affa8918884f2 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -729,15 +729,19 @@ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher); impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { #[inline] - fn next(&mut self) -> Option<(usize, usize)> { - self.0.next_match() + fn next(&mut self) -> Option<(usize, &'a str)> { + self.0.next_match().map(|(start, end)| unsafe { + (start, self.0.haystack().slice_unchecked(start, end)) + }) } #[inline] - fn next_back(&mut self) -> Option<(usize, usize)> + fn next_back(&mut self) -> Option<(usize, &'a str)> where P::Searcher: ReverseSearcher<'a> { - self.0.next_match_back() + self.0.next_match_back().map(|(start, end)| unsafe { + (start, self.0.haystack().slice_unchecked(start, end)) + }) } } @@ -753,7 +757,7 @@ generate_pattern_iterators! { reason = "type may be removed or have its iterator impl changed", issue = "27743")] internal: - MatchIndicesInternal yielding ((usize, usize)); + MatchIndicesInternal yielding ((usize, &'a str)); delegate double ended; } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index ff732ee7b9d80..9d1674b74d1fc 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -331,10 +331,10 @@ fn split_msg_into_multilines(msg: &str) -> Option { let first = msg.match_indices("expected").filter(|s| { s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' || msg.char_at_reverse(s.0) == '(') - }).map(|(a, b)| (a - 1, b)); + }).map(|(a, b)| (a - 1, a + b.len())); let second = msg.match_indices("found").filter(|s| { msg.char_at_reverse(s.0) == ' ' - }).map(|(a, b)| (a - 1, b)); + }).map(|(a, b)| (a - 1, a + b.len())); let mut new_msg = String::new(); let mut head = 0; diff --git a/src/test/run-pass/issue-14919.rs b/src/test/run-pass/issue-14919.rs index 371e926ab18d5..d3c9fe9161ccb 100644 --- a/src/test/run-pass/issue-14919.rs +++ b/src/test/run-pass/issue-14919.rs @@ -59,5 +59,5 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi fn main() { let s = "abcbdef"; match_indices(s, |c: char| c == 'b') - .collect::>(); + .collect::>(); }