Skip to content

Commit 58b33ad

Browse files
committed
Auto merge of #41659 - bluss:clone-split-whitespace, r=aturon
impl Clone for .split_whitespace() Use custom closure structs for the predicates so that the iterator's clone can simply be derived. This should also reduce virtual call overhead by not using function pointers. Fixes #41655
2 parents db1c9eb + 41aeb9d commit 58b33ad

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

src/libstd_unicode/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@
3636
#![feature(core_char_ext)]
3737
#![feature(decode_utf8)]
3838
#![feature(fused)]
39+
#![feature(fn_traits)]
3940
#![feature(lang_items)]
4041
#![feature(staged_api)]
4142
#![feature(try_from)]
43+
#![feature(unboxed_closures)]
4244

4345
mod tables;
4446
mod u_str;

src/libstd_unicode/u_str.rs

+42-12
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ use core::str::Split;
2626
/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
2727
/// [`str`]: ../../std/primitive.str.html
2828
#[stable(feature = "split_whitespace", since = "1.1.0")]
29+
#[derive(Clone)]
2930
pub struct SplitWhitespace<'a> {
30-
inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
31+
inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
3132
}
3233

3334
/// Methods for Unicode string slices
@@ -44,17 +45,7 @@ pub trait UnicodeStr {
4445
impl UnicodeStr for str {
4546
#[inline]
4647
fn split_whitespace(&self) -> SplitWhitespace {
47-
fn is_not_empty(s: &&str) -> bool {
48-
!s.is_empty()
49-
}
50-
let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
51-
52-
fn is_whitespace(c: char) -> bool {
53-
c.is_whitespace()
54-
}
55-
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
56-
57-
SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
48+
SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
5849
}
5950

6051
#[inline]
@@ -139,6 +130,45 @@ impl<I> Iterator for Utf16Encoder<I>
139130
impl<I> FusedIterator for Utf16Encoder<I>
140131
where I: FusedIterator<Item = char> {}
141132

133+
#[derive(Clone)]
134+
struct IsWhitespace;
135+
136+
impl FnOnce<(char, )> for IsWhitespace {
137+
type Output = bool;
138+
139+
#[inline]
140+
extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
141+
self.call_mut(arg)
142+
}
143+
}
144+
145+
impl FnMut<(char, )> for IsWhitespace {
146+
#[inline]
147+
extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
148+
arg.0.is_whitespace()
149+
}
150+
}
151+
152+
#[derive(Clone)]
153+
struct IsNotEmpty;
154+
155+
impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
156+
type Output = bool;
157+
158+
#[inline]
159+
extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
160+
self.call_mut(arg)
161+
}
162+
}
163+
164+
impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
165+
#[inline]
166+
extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
167+
!arg.0.is_empty()
168+
}
169+
}
170+
171+
142172
#[stable(feature = "split_whitespace", since = "1.1.0")]
143173
impl<'a> Iterator for SplitWhitespace<'a> {
144174
type Item = &'a str;

0 commit comments

Comments
 (0)