Skip to content

Commit b435960

Browse files
committed
Auto merge of #95644 - WaffleLapkin:str_split_as_str_refactor_take2, r=Amanieu
`Split*::as_str` refactor I've made this patch almost a year ago, so the rename and the behavior change are in one commit, sorry 😅 This fixes #84974, as it's required to make other changes work. This PR - Renames `as_str` method of string `Split*` iterators to `remainder` (it seems like the `as_str` name was confusing to users) - Makes `remainder` return `Option<&str>`, to distinguish between "the iterator is exhausted" and "the tail is empty", this was [required on the tracking issue](#77998 (comment)) r? `@m-ou-se`
2 parents 3b1c8a9 + b458a49 commit b435960

File tree

2 files changed

+104
-84
lines changed

2 files changed

+104
-84
lines changed

library/core/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
#![feature(const_unsafecell_get_mut)]
159159
#![feature(const_waker)]
160160
#![feature(core_panic)]
161+
#![feature(char_indices_offset)]
161162
#![feature(duration_consts_float)]
162163
#![feature(maybe_uninit_uninit_array)]
163164
#![feature(ptr_alignment_type)]
@@ -166,6 +167,8 @@
166167
#![feature(slice_ptr_get)]
167168
#![feature(slice_split_at_unchecked)]
168169
#![feature(str_internals)]
170+
#![feature(str_split_remainder)]
171+
#![feature(str_split_inclusive_remainder)]
169172
#![feature(strict_provenance)]
170173
#![feature(utf16_extra)]
171174
#![feature(utf16_extra_const)]

library/core/src/str/iter.rs

+101-84
Original file line numberDiff line numberDiff line change
@@ -585,16 +585,17 @@ where
585585
impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
586586
#[inline]
587587
fn get_end(&mut self) -> Option<&'a str> {
588-
if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
588+
if !self.finished {
589589
self.finished = true;
590-
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
591-
unsafe {
592-
let string = self.matcher.haystack().get_unchecked(self.start..self.end);
593-
Some(string)
590+
591+
if self.allow_trailing_empty || self.end - self.start > 0 {
592+
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
593+
let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) };
594+
return Some(string);
594595
}
595-
} else {
596-
None
597596
}
597+
598+
None
598599
}
599600

600601
#[inline]
@@ -716,14 +717,14 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
716717
}
717718

718719
#[inline]
719-
fn as_str(&self) -> &'a str {
720+
fn remainder(&self) -> Option<&'a str> {
720721
// `Self::get_end` doesn't change `self.start`
721722
if self.finished {
722-
return "";
723+
return None;
723724
}
724725

725726
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
726-
unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
727+
Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) })
727728
}
728729
}
729730

@@ -746,44 +747,48 @@ generate_pattern_iterators! {
746747
}
747748

748749
impl<'a, P: Pattern<'a>> Split<'a, P> {
749-
/// Returns remainder of the split string
750+
/// Returns remainder of the split string.
751+
///
752+
/// If the iterator is empty, returns `None`.
750753
///
751754
/// # Examples
752755
///
753756
/// ```
754-
/// #![feature(str_split_as_str)]
757+
/// #![feature(str_split_remainder)]
755758
/// let mut split = "Mary had a little lamb".split(' ');
756-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
759+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
757760
/// split.next();
758-
/// assert_eq!(split.as_str(), "had a little lamb");
761+
/// assert_eq!(split.remainder(), Some("had a little lamb"));
759762
/// split.by_ref().for_each(drop);
760-
/// assert_eq!(split.as_str(), "");
763+
/// assert_eq!(split.remainder(), None);
761764
/// ```
762765
#[inline]
763-
#[unstable(feature = "str_split_as_str", issue = "77998")]
764-
pub fn as_str(&self) -> &'a str {
765-
self.0.as_str()
766+
#[unstable(feature = "str_split_remainder", issue = "77998")]
767+
pub fn remainder(&self) -> Option<&'a str> {
768+
self.0.remainder()
766769
}
767770
}
768771

769772
impl<'a, P: Pattern<'a>> RSplit<'a, P> {
770-
/// Returns remainder of the split string
773+
/// Returns remainder of the split string.
774+
///
775+
/// If the iterator is empty, returns `None`.
771776
///
772777
/// # Examples
773778
///
774779
/// ```
775-
/// #![feature(str_split_as_str)]
780+
/// #![feature(str_split_remainder)]
776781
/// let mut split = "Mary had a little lamb".rsplit(' ');
777-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
782+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
778783
/// split.next();
779-
/// assert_eq!(split.as_str(), "Mary had a little");
784+
/// assert_eq!(split.remainder(), Some("Mary had a little"));
780785
/// split.by_ref().for_each(drop);
781-
/// assert_eq!(split.as_str(), "");
786+
/// assert_eq!(split.remainder(), None);
782787
/// ```
783788
#[inline]
784-
#[unstable(feature = "str_split_as_str", issue = "77998")]
785-
pub fn as_str(&self) -> &'a str {
786-
self.0.as_str()
789+
#[unstable(feature = "str_split_remainder", issue = "77998")]
790+
pub fn remainder(&self) -> Option<&'a str> {
791+
self.0.remainder()
787792
}
788793
}
789794

@@ -806,44 +811,48 @@ generate_pattern_iterators! {
806811
}
807812

808813
impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
809-
/// Returns remainder of the split string
814+
/// Returns remainder of the split string.
815+
///
816+
/// If the iterator is empty, returns `None`.
810817
///
811818
/// # Examples
812819
///
813820
/// ```
814-
/// #![feature(str_split_as_str)]
821+
/// #![feature(str_split_remainder)]
815822
/// let mut split = "A..B..".split_terminator('.');
816-
/// assert_eq!(split.as_str(), "A..B..");
823+
/// assert_eq!(split.remainder(), Some("A..B.."));
817824
/// split.next();
818-
/// assert_eq!(split.as_str(), ".B..");
825+
/// assert_eq!(split.remainder(), Some(".B.."));
819826
/// split.by_ref().for_each(drop);
820-
/// assert_eq!(split.as_str(), "");
827+
/// assert_eq!(split.remainder(), None);
821828
/// ```
822829
#[inline]
823-
#[unstable(feature = "str_split_as_str", issue = "77998")]
824-
pub fn as_str(&self) -> &'a str {
825-
self.0.as_str()
830+
#[unstable(feature = "str_split_remainder", issue = "77998")]
831+
pub fn remainder(&self) -> Option<&'a str> {
832+
self.0.remainder()
826833
}
827834
}
828835

829836
impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
830-
/// Returns remainder of the split string
837+
/// Returns remainder of the split string.
838+
///
839+
/// If the iterator is empty, returns `None`.
831840
///
832841
/// # Examples
833842
///
834843
/// ```
835-
/// #![feature(str_split_as_str)]
844+
/// #![feature(str_split_remainder)]
836845
/// let mut split = "A..B..".rsplit_terminator('.');
837-
/// assert_eq!(split.as_str(), "A..B..");
846+
/// assert_eq!(split.remainder(), Some("A..B.."));
838847
/// split.next();
839-
/// assert_eq!(split.as_str(), "A..B");
848+
/// assert_eq!(split.remainder(), Some("A..B"));
840849
/// split.by_ref().for_each(drop);
841-
/// assert_eq!(split.as_str(), "");
850+
/// assert_eq!(split.remainder(), None);
842851
/// ```
843852
#[inline]
844-
#[unstable(feature = "str_split_as_str", issue = "77998")]
845-
pub fn as_str(&self) -> &'a str {
846-
self.0.as_str()
853+
#[unstable(feature = "str_split_remainder", issue = "77998")]
854+
pub fn remainder(&self) -> Option<&'a str> {
855+
self.0.remainder()
847856
}
848857
}
849858

@@ -905,8 +914,8 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
905914
}
906915

907916
#[inline]
908-
fn as_str(&self) -> &'a str {
909-
self.iter.as_str()
917+
fn remainder(&self) -> Option<&'a str> {
918+
self.iter.remainder()
910919
}
911920
}
912921

@@ -929,44 +938,48 @@ generate_pattern_iterators! {
929938
}
930939

931940
impl<'a, P: Pattern<'a>> SplitN<'a, P> {
932-
/// Returns remainder of the split string
941+
/// Returns remainder of the split string.
942+
///
943+
/// If the iterator is empty, returns `None`.
933944
///
934945
/// # Examples
935946
///
936947
/// ```
937-
/// #![feature(str_split_as_str)]
948+
/// #![feature(str_split_remainder)]
938949
/// let mut split = "Mary had a little lamb".splitn(3, ' ');
939-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
950+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
940951
/// split.next();
941-
/// assert_eq!(split.as_str(), "had a little lamb");
952+
/// assert_eq!(split.remainder(), Some("had a little lamb"));
942953
/// split.by_ref().for_each(drop);
943-
/// assert_eq!(split.as_str(), "");
954+
/// assert_eq!(split.remainder(), None);
944955
/// ```
945956
#[inline]
946-
#[unstable(feature = "str_split_as_str", issue = "77998")]
947-
pub fn as_str(&self) -> &'a str {
948-
self.0.as_str()
957+
#[unstable(feature = "str_split_remainder", issue = "77998")]
958+
pub fn remainder(&self) -> Option<&'a str> {
959+
self.0.remainder()
949960
}
950961
}
951962

952963
impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
953-
/// Returns remainder of the split string
964+
/// Returns remainder of the split string.
965+
///
966+
/// If the iterator is empty, returns `None`.
954967
///
955968
/// # Examples
956969
///
957970
/// ```
958-
/// #![feature(str_split_as_str)]
971+
/// #![feature(str_split_remainder)]
959972
/// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
960-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
973+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
961974
/// split.next();
962-
/// assert_eq!(split.as_str(), "Mary had a little");
975+
/// assert_eq!(split.remainder(), Some("Mary had a little"));
963976
/// split.by_ref().for_each(drop);
964-
/// assert_eq!(split.as_str(), "");
977+
/// assert_eq!(split.remainder(), None);
965978
/// ```
966979
#[inline]
967-
#[unstable(feature = "str_split_as_str", issue = "77998")]
968-
pub fn as_str(&self) -> &'a str {
969-
self.0.as_str()
980+
#[unstable(feature = "str_split_remainder", issue = "77998")]
981+
pub fn remainder(&self) -> Option<&'a str> {
982+
self.0.remainder()
970983
}
971984
}
972985

@@ -1239,22 +1252,22 @@ impl<'a> SplitWhitespace<'a> {
12391252
/// # Examples
12401253
///
12411254
/// ```
1242-
/// #![feature(str_split_whitespace_as_str)]
1255+
/// #![feature(str_split_whitespace_remainder)]
12431256
///
12441257
/// let mut split = "Mary had a little lamb".split_whitespace();
1245-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
1258+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
12461259
///
12471260
/// split.next();
1248-
/// assert_eq!(split.as_str(), "had a little lamb");
1261+
/// assert_eq!(split.remainder(), Some("had a little lamb"));
12491262
///
12501263
/// split.by_ref().for_each(drop);
1251-
/// assert_eq!(split.as_str(), "");
1264+
/// assert_eq!(split.remainder(), None);
12521265
/// ```
12531266
#[inline]
12541267
#[must_use]
1255-
#[unstable(feature = "str_split_whitespace_as_str", issue = "77998")]
1256-
pub fn as_str(&self) -> &'a str {
1257-
self.inner.iter.as_str()
1268+
#[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
1269+
pub fn remainder(&self) -> Option<&'a str> {
1270+
self.inner.iter.remainder()
12581271
}
12591272
}
12601273

@@ -1290,32 +1303,34 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
12901303
impl FusedIterator for SplitAsciiWhitespace<'_> {}
12911304

12921305
impl<'a> SplitAsciiWhitespace<'a> {
1293-
/// Returns remainder of the split string
1306+
/// Returns remainder of the split string.
1307+
///
1308+
/// If the iterator is empty, returns `None`.
12941309
///
12951310
/// # Examples
12961311
///
12971312
/// ```
1298-
/// #![feature(str_split_whitespace_as_str)]
1313+
/// #![feature(str_split_whitespace_remainder)]
12991314
///
13001315
/// let mut split = "Mary had a little lamb".split_ascii_whitespace();
1301-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
1316+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
13021317
///
13031318
/// split.next();
1304-
/// assert_eq!(split.as_str(), "had a little lamb");
1319+
/// assert_eq!(split.remainder(), Some("had a little lamb"));
13051320
///
13061321
/// split.by_ref().for_each(drop);
1307-
/// assert_eq!(split.as_str(), "");
1322+
/// assert_eq!(split.remainder(), None);
13081323
/// ```
13091324
#[inline]
13101325
#[must_use]
1311-
#[unstable(feature = "str_split_whitespace_as_str", issue = "77998")]
1312-
pub fn as_str(&self) -> &'a str {
1326+
#[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
1327+
pub fn remainder(&self) -> Option<&'a str> {
13131328
if self.inner.iter.iter.finished {
1314-
return "";
1329+
return None;
13151330
}
13161331

13171332
// SAFETY: Slice is created from str.
1318-
unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) }
1333+
Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) })
13191334
}
13201335
}
13211336

@@ -1358,23 +1373,25 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
13581373
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
13591374

13601375
impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
1361-
/// Returns remainder of the split string
1376+
/// Returns remainder of the split string.
1377+
///
1378+
/// If the iterator is empty, returns `None`.
13621379
///
13631380
/// # Examples
13641381
///
13651382
/// ```
1366-
/// #![feature(str_split_inclusive_as_str)]
1383+
/// #![feature(str_split_inclusive_remainder)]
13671384
/// let mut split = "Mary had a little lamb".split_inclusive(' ');
1368-
/// assert_eq!(split.as_str(), "Mary had a little lamb");
1385+
/// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
13691386
/// split.next();
1370-
/// assert_eq!(split.as_str(), "had a little lamb");
1387+
/// assert_eq!(split.remainder(), Some("had a little lamb"));
13711388
/// split.by_ref().for_each(drop);
1372-
/// assert_eq!(split.as_str(), "");
1389+
/// assert_eq!(split.remainder(), None);
13731390
/// ```
13741391
#[inline]
1375-
#[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
1376-
pub fn as_str(&self) -> &'a str {
1377-
self.0.as_str()
1392+
#[unstable(feature = "str_split_inclusive_remainder", issue = "77998")]
1393+
pub fn remainder(&self) -> Option<&'a str> {
1394+
self.0.remainder()
13781395
}
13791396
}
13801397

0 commit comments

Comments
 (0)