Skip to content

Commit 83cd669

Browse files
authored
Rollup merge of #139745 - thaliaarchi:iter-unused-clone-copy, r=joboet
Avoid unused clones in `Cloned<I>` and `Copied<I>` Avoid cloning in `Cloned<I>` or copying in `Copied<I>` when elements are only needed by reference or not at all. There is already some precedent for this, given that `__iterator_get_unchecked` is implemented, which can skip elements. The reduced clones are technically observable by a user impl of `Clone`. r? libs-api
2 parents d179ea0 + ed5f31a commit 83cd669

File tree

2 files changed

+163
-20
lines changed

2 files changed

+163
-20
lines changed

Diff for: library/core/src/iter/adapters/cloned.rs

+86-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::num::NonZero;
22

3+
use crate::cmp::Ordering;
34
use crate::iter::adapters::zip::try_get_unchecked;
45
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
56
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
@@ -41,13 +42,31 @@ where
4142
self.it.next().cloned()
4243
}
4344

45+
#[inline]
4446
fn size_hint(&self) -> (usize, Option<usize>) {
4547
self.it.size_hint()
4648
}
4749

50+
#[inline]
51+
fn count(self) -> usize {
52+
self.it.count()
53+
}
54+
55+
fn last(self) -> Option<T> {
56+
self.it.last().cloned()
57+
}
58+
59+
#[inline]
60+
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
61+
self.it.advance_by(n)
62+
}
63+
64+
fn nth(&mut self, n: usize) -> Option<T> {
65+
self.it.nth(n).cloned()
66+
}
67+
4868
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
4969
where
50-
Self: Sized,
5170
F: FnMut(B, Self::Item) -> R,
5271
R: Try<Output = B>,
5372
{
@@ -61,6 +80,58 @@ where
6180
self.it.map(T::clone).fold(init, f)
6281
}
6382

83+
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
84+
where
85+
P: FnMut(&Self::Item) -> bool,
86+
{
87+
self.it.find(move |x| predicate(&x)).cloned()
88+
}
89+
90+
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
91+
where
92+
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
93+
{
94+
self.it.max_by(move |&x, &y| compare(x, y)).cloned()
95+
}
96+
97+
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
98+
where
99+
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
100+
{
101+
self.it.min_by(move |&x, &y| compare(x, y)).cloned()
102+
}
103+
104+
fn cmp<O>(self, other: O) -> Ordering
105+
where
106+
O: IntoIterator<Item = Self::Item>,
107+
Self::Item: Ord,
108+
{
109+
self.it.cmp_by(other, |x, y| x.cmp(&y))
110+
}
111+
112+
fn partial_cmp<O>(self, other: O) -> Option<Ordering>
113+
where
114+
O: IntoIterator,
115+
Self::Item: PartialOrd<O::Item>,
116+
{
117+
self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
118+
}
119+
120+
fn eq<O>(self, other: O) -> bool
121+
where
122+
O: IntoIterator,
123+
Self::Item: PartialEq<O::Item>,
124+
{
125+
self.it.eq_by(other, |x, y| x == &y)
126+
}
127+
128+
fn is_sorted_by<F>(self, mut compare: F) -> bool
129+
where
130+
F: FnMut(&Self::Item, &Self::Item) -> bool,
131+
{
132+
self.it.is_sorted_by(move |&x, &y| compare(x, y))
133+
}
134+
64135
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
65136
where
66137
Self: TrustedRandomAccessNoCoerce,
@@ -81,9 +152,13 @@ where
81152
self.it.next_back().cloned()
82153
}
83154

155+
#[inline]
156+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
157+
self.it.advance_back_by(n)
158+
}
159+
84160
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
85161
where
86-
Self: Sized,
87162
F: FnMut(B, Self::Item) -> R,
88163
R: Try<Output = B>,
89164
{
@@ -96,6 +171,13 @@ where
96171
{
97172
self.it.map(T::clone).rfold(init, f)
98173
}
174+
175+
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
176+
where
177+
P: FnMut(&Self::Item) -> bool,
178+
{
179+
self.it.rfind(move |x| predicate(&x)).cloned()
180+
}
99181
}
100182

101183
#[stable(feature = "iter_cloned", since = "1.1.0")]
@@ -104,10 +186,12 @@ where
104186
I: ExactSizeIterator<Item = &'a T>,
105187
T: Clone,
106188
{
189+
#[inline]
107190
fn len(&self) -> usize {
108191
self.it.len()
109192
}
110193

194+
#[inline]
111195
fn is_empty(&self) -> bool {
112196
self.it.is_empty()
113197
}

Diff for: library/core/src/iter/adapters/copied.rs

+77-18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::cmp::Ordering;
12
use crate::iter::adapters::zip::try_get_unchecked;
23
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
34
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
@@ -48,20 +49,35 @@ where
4849

4950
fn next_chunk<const N: usize>(
5051
&mut self,
51-
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
52-
where
53-
Self: Sized,
54-
{
52+
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
5553
<I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
5654
}
5755

56+
#[inline]
5857
fn size_hint(&self) -> (usize, Option<usize>) {
5958
self.it.size_hint()
6059
}
6160

61+
#[inline]
62+
fn count(self) -> usize {
63+
self.it.count()
64+
}
65+
66+
fn last(self) -> Option<T> {
67+
self.it.last().copied()
68+
}
69+
70+
#[inline]
71+
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
72+
self.it.advance_by(n)
73+
}
74+
75+
fn nth(&mut self, n: usize) -> Option<T> {
76+
self.it.nth(n).copied()
77+
}
78+
6279
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
6380
where
64-
Self: Sized,
6581
F: FnMut(B, Self::Item) -> R,
6682
R: Try<Output = B>,
6783
{
@@ -75,21 +91,56 @@ where
7591
self.it.fold(init, copy_fold(f))
7692
}
7793

78-
fn nth(&mut self, n: usize) -> Option<T> {
79-
self.it.nth(n).copied()
94+
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
95+
where
96+
P: FnMut(&Self::Item) -> bool,
97+
{
98+
self.it.find(move |x| predicate(&x)).copied()
8099
}
81100

82-
fn last(self) -> Option<T> {
83-
self.it.last().copied()
101+
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
102+
where
103+
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
104+
{
105+
self.it.max_by(move |&x, &y| compare(x, y)).copied()
84106
}
85107

86-
fn count(self) -> usize {
87-
self.it.count()
108+
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
109+
where
110+
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
111+
{
112+
self.it.min_by(move |&x, &y| compare(x, y)).copied()
88113
}
89114

90-
#[inline]
91-
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
92-
self.it.advance_by(n)
115+
fn cmp<O>(self, other: O) -> Ordering
116+
where
117+
O: IntoIterator<Item = Self::Item>,
118+
Self::Item: Ord,
119+
{
120+
self.it.cmp_by(other, |x, y| x.cmp(&y))
121+
}
122+
123+
fn partial_cmp<O>(self, other: O) -> Option<Ordering>
124+
where
125+
O: IntoIterator,
126+
Self::Item: PartialOrd<O::Item>,
127+
{
128+
self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
129+
}
130+
131+
fn eq<O>(self, other: O) -> bool
132+
where
133+
O: IntoIterator,
134+
Self::Item: PartialEq<O::Item>,
135+
{
136+
self.it.eq_by(other, |x, y| x == &y)
137+
}
138+
139+
fn is_sorted_by<F>(self, mut compare: F) -> bool
140+
where
141+
F: FnMut(&Self::Item, &Self::Item) -> bool,
142+
{
143+
self.it.is_sorted_by(move |&x, &y| compare(x, y))
93144
}
94145

95146
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
@@ -112,9 +163,13 @@ where
112163
self.it.next_back().copied()
113164
}
114165

166+
#[inline]
167+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
168+
self.it.advance_back_by(n)
169+
}
170+
115171
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
116172
where
117-
Self: Sized,
118173
F: FnMut(B, Self::Item) -> R,
119174
R: Try<Output = B>,
120175
{
@@ -128,9 +183,11 @@ where
128183
self.it.rfold(init, copy_fold(f))
129184
}
130185

131-
#[inline]
132-
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
133-
self.it.advance_back_by(n)
186+
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
187+
where
188+
P: FnMut(&Self::Item) -> bool,
189+
{
190+
self.it.rfind(move |x| predicate(&x)).copied()
134191
}
135192
}
136193

@@ -140,10 +197,12 @@ where
140197
I: ExactSizeIterator<Item = &'a T>,
141198
T: Copy,
142199
{
200+
#[inline]
143201
fn len(&self) -> usize {
144202
self.it.len()
145203
}
146204

205+
#[inline]
147206
fn is_empty(&self) -> bool {
148207
self.it.is_empty()
149208
}

0 commit comments

Comments
 (0)