Skip to content

Commit 4ea75af

Browse files
committed
Specialize internal state of Fuse depending on underlying iterator
1 parent 7520894 commit 4ea75af

File tree

1 file changed

+79
-182
lines changed

1 file changed

+79
-182
lines changed

src/libcore/iter/adapters/fuse.rs

+79-182
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,44 @@
1+
use crate::convert::Infallible;
12
use crate::intrinsics;
23
use crate::iter::{
34
DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess,
45
};
56
use crate::ops::Try;
67

8+
trait Stop: Sized {
9+
/// Switch internal state of `Fuse` to indicate that underlying iterator returned `None`
10+
fn stop<I>(state: &mut Result<I, Self>);
11+
}
12+
13+
impl Stop for () {
14+
fn stop<I>(state: &mut Result<I, Self>) {
15+
*state = Err(())
16+
}
17+
}
18+
19+
impl Stop for Infallible {
20+
#[inline(always)]
21+
fn stop<I>(_state: &mut Result<I, Self>) {
22+
// Intentionally does nothing: fused iterator returns `None`s after returning `None`,
23+
// so there is no need to alter state
24+
}
25+
}
26+
27+
trait StopState {
28+
/// Type of value used to indicate that iterator returned `None`
29+
type State: Stop + crate::fmt::Debug + Clone;
30+
}
31+
32+
impl<I: ?Sized> StopState for I {
33+
default type State = ();
34+
}
35+
36+
impl<I: FusedIterator + ?Sized> StopState for I {
37+
type State = Infallible;
38+
}
39+
40+
type StopStateOf<I> = <I as StopState>::State;
41+
742
/// An iterator that yields `None` forever after the underlying iterator
843
/// yields `None` once.
944
///
@@ -16,12 +51,17 @@ use crate::ops::Try;
1651
#[must_use = "iterators are lazy and do nothing unless consumed"]
1752
#[stable(feature = "rust1", since = "1.0.0")]
1853
pub struct Fuse<I> {
19-
// NOTE: for `I: FusedIterator`, this is always assumed `Some`!
20-
iter: Option<I>,
54+
iter: Result<I, StopStateOf<I>>,
2155
}
56+
2257
impl<I> Fuse<I> {
2358
pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
24-
Fuse { iter: Some(iter) }
59+
Fuse { iter: Ok(iter) }
60+
}
61+
62+
#[inline(always)]
63+
fn stop(&mut self) {
64+
StopStateOf::<I>::stop(&mut self.iter);
2565
}
2666
}
2767

@@ -36,71 +76,71 @@ where
3676
type Item = <I as Iterator>::Item;
3777

3878
#[inline]
39-
default fn next(&mut self) -> Option<<I as Iterator>::Item> {
40-
let next = self.iter.as_mut()?.next();
79+
fn next(&mut self) -> Option<<I as Iterator>::Item> {
80+
let next = self.iter.as_mut().ok()?.next();
4181
if next.is_none() {
42-
self.iter = None;
82+
self.stop();
4383
}
4484
next
4585
}
4686

4787
#[inline]
48-
default fn nth(&mut self, n: usize) -> Option<I::Item> {
49-
let nth = self.iter.as_mut()?.nth(n);
88+
fn nth(&mut self, n: usize) -> Option<I::Item> {
89+
let nth = self.iter.as_mut().ok()?.nth(n);
5090
if nth.is_none() {
51-
self.iter = None;
91+
self.stop();
5292
}
5393
nth
5494
}
5595

5696
#[inline]
57-
default fn last(self) -> Option<I::Item> {
58-
self.iter?.last()
97+
fn last(self) -> Option<I::Item> {
98+
self.iter.ok()?.last()
5999
}
60100

61101
#[inline]
62-
default fn count(self) -> usize {
102+
fn count(self) -> usize {
63103
self.iter.map_or(0, I::count)
64104
}
65105

66106
#[inline]
67-
default fn size_hint(&self) -> (usize, Option<usize>) {
107+
fn size_hint(&self) -> (usize, Option<usize>) {
68108
self.iter.as_ref().map_or((0, Some(0)), I::size_hint)
69109
}
70110

71111
#[inline]
72-
default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
112+
fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
73113
where
74114
Self: Sized,
75115
Fold: FnMut(Acc, Self::Item) -> R,
76116
R: Try<Ok = Acc>,
77117
{
78-
if let Some(ref mut iter) = self.iter {
118+
if let Ok(ref mut iter) = self.iter {
79119
acc = iter.try_fold(acc, fold)?;
80-
self.iter = None;
120+
self.stop();
81121
}
82122
Try::from_ok(acc)
83123
}
84124

85125
#[inline]
86-
default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
126+
fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
87127
where
88128
Fold: FnMut(Acc, Self::Item) -> Acc,
89129
{
90-
if let Some(iter) = self.iter {
130+
if let Ok(iter) = self.iter {
91131
acc = iter.fold(acc, fold);
92132
}
93133
acc
94134
}
95135

96136
#[inline]
97-
default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
137+
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
98138
where
99139
P: FnMut(&Self::Item) -> bool,
100140
{
101-
let found = self.iter.as_mut()?.find(predicate);
141+
let found = self.iter.as_mut().ok()?.find(predicate);
102142
if found.is_none() {
103-
self.iter = None;
143+
self.stop();
104144
}
105145
found
106146
}
@@ -112,56 +152,56 @@ where
112152
I: DoubleEndedIterator,
113153
{
114154
#[inline]
115-
default fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
116-
let next = self.iter.as_mut()?.next_back();
155+
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
156+
let next = self.iter.as_mut().ok()?.next_back();
117157
if next.is_none() {
118-
self.iter = None;
158+
self.stop();
119159
}
120160
next
121161
}
122162

123163
#[inline]
124-
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
125-
let nth = self.iter.as_mut()?.nth_back(n);
164+
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
165+
let nth = self.iter.as_mut().ok()?.nth_back(n);
126166
if nth.is_none() {
127-
self.iter = None;
167+
self.stop();
128168
}
129169
nth
130170
}
131171

132172
#[inline]
133-
default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
173+
fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
134174
where
135175
Self: Sized,
136176
Fold: FnMut(Acc, Self::Item) -> R,
137177
R: Try<Ok = Acc>,
138178
{
139-
if let Some(ref mut iter) = self.iter {
179+
if let Ok(ref mut iter) = self.iter {
140180
acc = iter.try_rfold(acc, fold)?;
141-
self.iter = None;
181+
self.stop();
142182
}
143183
Try::from_ok(acc)
144184
}
145185

146186
#[inline]
147-
default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
187+
fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
148188
where
149189
Fold: FnMut(Acc, Self::Item) -> Acc,
150190
{
151-
if let Some(iter) = self.iter {
191+
if let Ok(iter) = self.iter {
152192
acc = iter.rfold(acc, fold);
153193
}
154194
acc
155195
}
156196

157197
#[inline]
158-
default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
198+
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
159199
where
160200
P: FnMut(&Self::Item) -> bool,
161201
{
162-
let found = self.iter.as_mut()?.rfind(predicate);
202+
let found = self.iter.as_mut().ok()?.rfind(predicate);
163203
if found.is_none() {
164-
self.iter = None;
204+
self.stop();
165205
}
166206
found
167207
}
@@ -171,156 +211,13 @@ where
171211
impl<I> ExactSizeIterator for Fuse<I>
172212
where
173213
I: ExactSizeIterator,
174-
{
175-
default fn len(&self) -> usize {
176-
self.iter.as_ref().map_or(0, I::len)
177-
}
178-
179-
default fn is_empty(&self) -> bool {
180-
self.iter.as_ref().map_or(true, I::is_empty)
181-
}
182-
}
183-
184-
// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`
185-
impl<I: FusedIterator> Fuse<I> {
186-
#[inline(always)]
187-
fn as_inner(&self) -> &I {
188-
match self.iter {
189-
Some(ref iter) => iter,
190-
// SAFETY: the specialized iterator never sets `None`
191-
None => unsafe { intrinsics::unreachable() },
192-
}
193-
}
194-
195-
#[inline(always)]
196-
fn as_inner_mut(&mut self) -> &mut I {
197-
match self.iter {
198-
Some(ref mut iter) => iter,
199-
// SAFETY: the specialized iterator never sets `None`
200-
None => unsafe { intrinsics::unreachable() },
201-
}
202-
}
203-
204-
#[inline(always)]
205-
fn into_inner(self) -> I {
206-
match self.iter {
207-
Some(iter) => iter,
208-
// SAFETY: the specialized iterator never sets `None`
209-
None => unsafe { intrinsics::unreachable() },
210-
}
211-
}
212-
}
213-
214-
#[stable(feature = "fused", since = "1.26.0")]
215-
impl<I> Iterator for Fuse<I>
216-
where
217-
I: FusedIterator,
218-
{
219-
#[inline]
220-
fn next(&mut self) -> Option<<I as Iterator>::Item> {
221-
self.as_inner_mut().next()
222-
}
223-
224-
#[inline]
225-
fn nth(&mut self, n: usize) -> Option<I::Item> {
226-
self.as_inner_mut().nth(n)
227-
}
228-
229-
#[inline]
230-
fn last(self) -> Option<I::Item> {
231-
self.into_inner().last()
232-
}
233-
234-
#[inline]
235-
fn count(self) -> usize {
236-
self.into_inner().count()
237-
}
238-
239-
#[inline]
240-
fn size_hint(&self) -> (usize, Option<usize>) {
241-
self.as_inner().size_hint()
242-
}
243-
244-
#[inline]
245-
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
246-
where
247-
Self: Sized,
248-
Fold: FnMut(Acc, Self::Item) -> R,
249-
R: Try<Ok = Acc>,
250-
{
251-
self.as_inner_mut().try_fold(init, fold)
252-
}
253-
254-
#[inline]
255-
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
256-
where
257-
Fold: FnMut(Acc, Self::Item) -> Acc,
258-
{
259-
self.into_inner().fold(init, fold)
260-
}
261-
262-
#[inline]
263-
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
264-
where
265-
P: FnMut(&Self::Item) -> bool,
266-
{
267-
self.as_inner_mut().find(predicate)
268-
}
269-
}
270-
271-
#[stable(feature = "fused", since = "1.26.0")]
272-
impl<I> DoubleEndedIterator for Fuse<I>
273-
where
274-
I: DoubleEndedIterator + FusedIterator,
275-
{
276-
#[inline]
277-
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
278-
self.as_inner_mut().next_back()
279-
}
280-
281-
#[inline]
282-
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
283-
self.as_inner_mut().nth_back(n)
284-
}
285-
286-
#[inline]
287-
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
288-
where
289-
Self: Sized,
290-
Fold: FnMut(Acc, Self::Item) -> R,
291-
R: Try<Ok = Acc>,
292-
{
293-
self.as_inner_mut().try_rfold(init, fold)
294-
}
295-
296-
#[inline]
297-
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
298-
where
299-
Fold: FnMut(Acc, Self::Item) -> Acc,
300-
{
301-
self.into_inner().rfold(init, fold)
302-
}
303-
304-
#[inline]
305-
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
306-
where
307-
P: FnMut(&Self::Item) -> bool,
308-
{
309-
self.as_inner_mut().rfind(predicate)
310-
}
311-
}
312-
313-
#[stable(feature = "rust1", since = "1.0.0")]
314-
impl<I> ExactSizeIterator for Fuse<I>
315-
where
316-
I: ExactSizeIterator + FusedIterator,
317214
{
318215
fn len(&self) -> usize {
319-
self.as_inner().len()
216+
self.iter.as_ref().map_or(0, I::len)
320217
}
321218

322219
fn is_empty(&self) -> bool {
323-
self.as_inner().is_empty()
220+
self.iter.as_ref().map_or(true, I::is_empty)
324221
}
325222
}
326223

@@ -330,9 +227,9 @@ where
330227
{
331228
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
332229
match self.iter {
333-
Some(ref mut iter) => iter.get_unchecked(i),
230+
Ok(ref mut iter) => iter.get_unchecked(i),
334231
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
335-
None => intrinsics::unreachable(),
232+
Err(_) => intrinsics::unreachable(),
336233
}
337234
}
338235

0 commit comments

Comments
 (0)