Skip to content

Commit 0eacaab

Browse files
committed
Use TrustedRandomAccess for for _ in loops
1 parent f1b9b12 commit 0eacaab

File tree

5 files changed

+81
-4
lines changed

5 files changed

+81
-4
lines changed

library/core/src/iter/loop_desugar.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use crate::iter::IntoIterator as RealIntoIterator;
2+
use crate::iter::TrustedRandomAccessNoCoerce;
3+
4+
#[unstable(feature = "trusted_random_access", issue = "none")]
5+
#[doc(hidden)]
6+
7+
pub trait IntoIterator {
8+
type IntoIter: Iterator;
9+
10+
#[unstable(feature = "trusted_random_access", issue = "none")]
11+
// #[cfg_attr(not(bootstrap), lang = "loop_desugar")]
12+
#[cfg_attr(not(bootstrap), lang = "into_iter")]
13+
fn into_iter(self) -> Self::IntoIter;
14+
}
15+
16+
impl<C: RealIntoIterator> IntoIterator for C {
17+
type IntoIter = ForLoopDesugar<C::IntoIter>;
18+
19+
#[inline]
20+
fn into_iter(self) -> Self::IntoIter {
21+
ForLoopDesugar { iter: <Self as RealIntoIterator>::into_iter(self), idx: 0 }
22+
}
23+
}
24+
25+
#[derive(Debug)]
26+
#[doc(hidden)]
27+
#[unstable(feature = "trusted_random_access", issue = "none")]
28+
pub struct ForLoopDesugar<I> {
29+
iter: I,
30+
idx: usize,
31+
}
32+
33+
#[unstable(feature = "trusted_random_access", issue = "none")]
34+
impl<I: Iterator> Iterator for ForLoopDesugar<I> {
35+
type Item = I::Item;
36+
37+
#[inline]
38+
fn next(&mut self) -> Option<I::Item> {
39+
// self.iter.next_spec(&mut self.idx)
40+
self.next_spec()
41+
}
42+
}
43+
44+
trait DesugarSpec<T> {
45+
fn next_spec(&mut self) -> Option<T>;
46+
}
47+
48+
impl<I, T> DesugarSpec<T> for ForLoopDesugar<I>
49+
where
50+
I: Iterator<Item = T>,
51+
{
52+
#[inline]
53+
default fn next_spec(&mut self) -> Option<I::Item> {
54+
self.iter.next()
55+
}
56+
}
57+
58+
impl<I, T> DesugarSpec<T> for ForLoopDesugar<I>
59+
where
60+
I: TrustedRandomAccessNoCoerce + Iterator<Item = T>,
61+
{
62+
#[inline]
63+
fn next_spec(&mut self) -> Option<I::Item> {
64+
let idx = self.idx;
65+
if idx < self.iter.size() {
66+
// SAFETY: idx can't overflow since size is a usize. idx is always
67+
// less than size, so the index is always valid.
68+
unsafe {
69+
self.idx = idx.unchecked_add(1);
70+
Some(self.iter.__iterator_get_unchecked(idx))
71+
}
72+
} else {
73+
None
74+
}
75+
}
76+
}

library/core/src/iter/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ pub use self::adapters::{Intersperse, IntersperseWith};
419419
pub(crate) use self::adapters::{try_process, ByRefSized};
420420

421421
mod adapters;
422+
mod loop_desugar;
422423
mod range;
423424
mod sources;
424425
mod traits;

library/core/src/iter/traits/collect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ pub trait IntoIterator {
262262
/// assert_eq!(Some(3), iter.next());
263263
/// assert_eq!(None, iter.next());
264264
/// ```
265-
#[lang = "into_iter"]
265+
#[cfg_attr(bootstrap, lang = "into_iter")]
266266
#[stable(feature = "rust1", since = "1.0.0")]
267267
fn into_iter(self) -> Self::IntoIter;
268268
}

library/core/tests/iter/adapters/cloned.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn test_cloned_side_effects() {
3131
.zip(&[1]);
3232
for _ in iter {}
3333
}
34-
assert_eq!(count, 2);
34+
assert_eq!(count, 1);
3535
}
3636

3737
#[test]

library/core/tests/iter/adapters/zip.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ fn test_zip_cloned_sideffectful() {
119119

120120
for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}
121121

122-
assert_eq!(&xs, &[1, 1, 1, 0][..]);
122+
assert_eq!(&xs, &[1, 1, 0, 0][..]);
123123
assert_eq!(&ys, &[1, 1][..]);
124124

125125
let xs = [CountClone::new(), CountClone::new()];
@@ -138,7 +138,7 @@ fn test_zip_map_sideffectful() {
138138

139139
for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}
140140

141-
assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
141+
assert_eq!(&xs, &[1, 1, 1, 1, 0, 0]);
142142
assert_eq!(&ys, &[1, 1, 1, 1]);
143143

144144
let mut xs = [0; 4];

0 commit comments

Comments
 (0)