Skip to content

Commit ff223ff

Browse files
authored
Rollup merge of #98430 - camsteffen:flatten-refactor, r=joshtriplett
Refactor iter adapters with less macros Just some code cleanup. Introduced a util `and_then_or_clear` for each of chain, flatten and fuse iter adapter impls. This reduces code nicely for flatten, but admittedly the other modules are more of a lateral move replacing macros with a function. But I think consistency across the modules and avoiding macros when possible is good.
2 parents 400f435 + 6587dda commit ff223ff

File tree

3 files changed

+56
-117
lines changed

3 files changed

+56
-117
lines changed

library/core/src/iter/adapters/chain.rs

+19-53
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,6 @@ impl<A, B> Chain<A, B> {
3737
}
3838
}
3939

40-
/// Fuse the iterator if the expression is `None`.
41-
macro_rules! fuse {
42-
($self:ident . $iter:ident . $($call:tt)+) => {
43-
match $self.$iter {
44-
Some(ref mut iter) => match iter.$($call)+ {
45-
None => {
46-
$self.$iter = None;
47-
None
48-
}
49-
item => item,
50-
},
51-
None => None,
52-
}
53-
};
54-
}
55-
56-
/// Try an iterator method without fusing,
57-
/// like an inline `.as_mut().and_then(...)`
58-
macro_rules! maybe {
59-
($self:ident . $iter:ident . $($call:tt)+) => {
60-
match $self.$iter {
61-
Some(ref mut iter) => iter.$($call)+,
62-
None => None,
63-
}
64-
};
65-
}
66-
6740
#[stable(feature = "rust1", since = "1.0.0")]
6841
impl<A, B> Iterator for Chain<A, B>
6942
where
@@ -74,10 +47,7 @@ where
7447

7548
#[inline]
7649
fn next(&mut self) -> Option<A::Item> {
77-
match fuse!(self.a.next()) {
78-
None => maybe!(self.b.next()),
79-
item => item,
80-
}
50+
and_then_or_clear(&mut self.a, Iterator::next).or_else(|| self.b.as_mut()?.next())
8151
}
8252

8353
#[inline]
@@ -161,31 +131,23 @@ where
161131
self.a = None;
162132
}
163133

164-
maybe!(self.b.nth(n))
134+
self.b.as_mut()?.nth(n)
165135
}
166136

167137
#[inline]
168138
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
169139
where
170140
P: FnMut(&Self::Item) -> bool,
171141
{
172-
match fuse!(self.a.find(&mut predicate)) {
173-
None => maybe!(self.b.find(predicate)),
174-
item => item,
175-
}
142+
and_then_or_clear(&mut self.a, |a| a.find(&mut predicate))
143+
.or_else(|| self.b.as_mut()?.find(predicate))
176144
}
177145

178146
#[inline]
179147
fn last(self) -> Option<A::Item> {
180148
// Must exhaust a before b.
181-
let a_last = match self.a {
182-
Some(a) => a.last(),
183-
None => None,
184-
};
185-
let b_last = match self.b {
186-
Some(b) => b.last(),
187-
None => None,
188-
};
149+
let a_last = self.a.and_then(Iterator::last);
150+
let b_last = self.b.and_then(Iterator::last);
189151
b_last.or(a_last)
190152
}
191153

@@ -220,10 +182,7 @@ where
220182
{
221183
#[inline]
222184
fn next_back(&mut self) -> Option<A::Item> {
223-
match fuse!(self.b.next_back()) {
224-
None => maybe!(self.a.next_back()),
225-
item => item,
226-
}
185+
and_then_or_clear(&mut self.b, |b| b.next_back()).or_else(|| self.a.as_mut()?.next_back())
227186
}
228187

229188
#[inline]
@@ -263,18 +222,16 @@ where
263222
self.b = None;
264223
}
265224

266-
maybe!(self.a.nth_back(n))
225+
self.a.as_mut()?.nth_back(n)
267226
}
268227

269228
#[inline]
270229
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
271230
where
272231
P: FnMut(&Self::Item) -> bool,
273232
{
274-
match fuse!(self.b.rfind(&mut predicate)) {
275-
None => maybe!(self.a.rfind(predicate)),
276-
item => item,
277-
}
233+
and_then_or_clear(&mut self.b, |b| b.rfind(&mut predicate))
234+
.or_else(|| self.a.as_mut()?.rfind(predicate))
278235
}
279236

280237
fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
@@ -324,3 +281,12 @@ where
324281
B: TrustedLen<Item = A::Item>,
325282
{
326283
}
284+
285+
#[inline]
286+
fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
287+
let x = f(opt.as_mut()?);
288+
if x.is_none() {
289+
*opt = None;
290+
}
291+
x
292+
}

library/core/src/iter/adapters/flatten.rs

+16-25
Original file line numberDiff line numberDiff line change
@@ -290,20 +290,11 @@ where
290290
#[inline]
291291
fn next(&mut self) -> Option<U::Item> {
292292
loop {
293-
if let Some(ref mut inner) = self.frontiter {
294-
match inner.next() {
295-
None => self.frontiter = None,
296-
elt @ Some(_) => return elt,
297-
}
293+
if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) {
294+
return elt;
298295
}
299296
match self.iter.next() {
300-
None => match self.backiter.as_mut()?.next() {
301-
None => {
302-
self.backiter = None;
303-
return None;
304-
}
305-
elt @ Some(_) => return elt,
306-
},
297+
None => return and_then_or_clear(&mut self.backiter, Iterator::next),
307298
Some(inner) => self.frontiter = Some(inner.into_iter()),
308299
}
309300
}
@@ -436,21 +427,12 @@ where
436427
#[inline]
437428
fn next_back(&mut self) -> Option<U::Item> {
438429
loop {
439-
if let Some(ref mut inner) = self.backiter {
440-
match inner.next_back() {
441-
None => self.backiter = None,
442-
elt @ Some(_) => return elt,
443-
}
430+
if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) {
431+
return elt;
444432
}
445433
match self.iter.next_back() {
446-
None => match self.frontiter.as_mut()?.next_back() {
447-
None => {
448-
self.frontiter = None;
449-
return None;
450-
}
451-
elt @ Some(_) => return elt,
452-
},
453-
next => self.backiter = next.map(IntoIterator::into_iter),
434+
None => return and_then_or_clear(&mut self.frontiter, |f| f.next_back()),
435+
Some(inner) => self.backiter = Some(inner.into_iter()),
454436
}
455437
}
456438
}
@@ -606,3 +588,12 @@ unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {}
606588
unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {}
607589
#[unstable(feature = "std_internals", issue = "none")]
608590
unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {}
591+
592+
#[inline]
593+
fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
594+
let x = f(opt.as_mut()?);
595+
if x.is_none() {
596+
*opt = None;
597+
}
598+
x
599+
}

library/core/src/iter/adapters/fuse.rs

+21-39
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,6 @@ impl<I> Fuse<I> {
2929
#[stable(feature = "fused", since = "1.26.0")]
3030
impl<I> FusedIterator for Fuse<I> where I: Iterator {}
3131

32-
/// Fuse the iterator if the expression is `None`.
33-
macro_rules! fuse {
34-
($self:ident . iter . $($call:tt)+) => {
35-
match $self.iter {
36-
Some(ref mut iter) => match iter.$($call)+ {
37-
None => {
38-
$self.iter = None;
39-
None
40-
}
41-
item => item,
42-
},
43-
None => None,
44-
}
45-
};
46-
}
47-
48-
/// Specialized macro that doesn't check if the expression is `None`.
49-
/// (We trust that a `FusedIterator` will fuse itself.)
50-
macro_rules! spec {
51-
($self:ident . iter . $($call:tt)+) => {
52-
match $self.iter {
53-
Some(ref mut iter) => iter.$($call)+,
54-
None => None,
55-
}
56-
};
57-
}
58-
5932
// Any specialized implementation here is made internal
6033
// to avoid exposing default fns outside this trait.
6134
#[stable(feature = "rust1", since = "1.0.0")]
@@ -281,12 +254,12 @@ where
281254

282255
#[inline]
283256
default fn next(&mut self) -> Option<<I as Iterator>::Item> {
284-
fuse!(self.iter.next())
257+
and_then_or_clear(&mut self.iter, Iterator::next)
285258
}
286259

287260
#[inline]
288261
default fn nth(&mut self, n: usize) -> Option<I::Item> {
289-
fuse!(self.iter.nth(n))
262+
and_then_or_clear(&mut self.iter, |iter| iter.nth(n))
290263
}
291264

292265
#[inline]
@@ -308,23 +281,23 @@ where
308281
where
309282
P: FnMut(&Self::Item) -> bool,
310283
{
311-
fuse!(self.iter.find(predicate))
284+
and_then_or_clear(&mut self.iter, |iter| iter.find(predicate))
312285
}
313286

314287
#[inline]
315288
default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
316289
where
317290
I: DoubleEndedIterator,
318291
{
319-
fuse!(self.iter.next_back())
292+
and_then_or_clear(&mut self.iter, |iter| iter.next_back())
320293
}
321294

322295
#[inline]
323296
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
324297
where
325298
I: DoubleEndedIterator,
326299
{
327-
fuse!(self.iter.nth_back(n))
300+
and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n))
328301
}
329302

330303
#[inline]
@@ -348,7 +321,7 @@ where
348321
P: FnMut(&Self::Item) -> bool,
349322
I: DoubleEndedIterator,
350323
{
351-
fuse!(self.iter.rfind(predicate))
324+
and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate))
352325
}
353326
}
354327

@@ -361,12 +334,12 @@ where
361334
{
362335
#[inline]
363336
fn next(&mut self) -> Option<<I as Iterator>::Item> {
364-
spec!(self.iter.next())
337+
self.iter.as_mut()?.next()
365338
}
366339

367340
#[inline]
368341
fn nth(&mut self, n: usize) -> Option<I::Item> {
369-
spec!(self.iter.nth(n))
342+
self.iter.as_mut()?.nth(n)
370343
}
371344

372345
#[inline]
@@ -387,23 +360,23 @@ where
387360
where
388361
P: FnMut(&Self::Item) -> bool,
389362
{
390-
spec!(self.iter.find(predicate))
363+
self.iter.as_mut()?.find(predicate)
391364
}
392365

393366
#[inline]
394367
fn next_back(&mut self) -> Option<<I as Iterator>::Item>
395368
where
396369
I: DoubleEndedIterator,
397370
{
398-
spec!(self.iter.next_back())
371+
self.iter.as_mut()?.next_back()
399372
}
400373

401374
#[inline]
402375
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
403376
where
404377
I: DoubleEndedIterator,
405378
{
406-
spec!(self.iter.nth_back(n))
379+
self.iter.as_mut()?.nth_back(n)
407380
}
408381

409382
#[inline]
@@ -426,6 +399,15 @@ where
426399
P: FnMut(&Self::Item) -> bool,
427400
I: DoubleEndedIterator,
428401
{
429-
spec!(self.iter.rfind(predicate))
402+
self.iter.as_mut()?.rfind(predicate)
403+
}
404+
}
405+
406+
#[inline]
407+
fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
408+
let x = f(opt.as_mut()?);
409+
if x.is_none() {
410+
*opt = None;
430411
}
412+
x
431413
}

0 commit comments

Comments
 (0)