Skip to content

Commit 0b534b3

Browse files
committed
Remove fake IntoIterator trait, invoke ForLoopDesugar directly and run cleanup on drop
The on-drop cleanup will enable using TRA in try_fold(&mut self) and implementing TRA for &mut Iterator
1 parent 7d10caf commit 0b534b3

File tree

17 files changed

+299
-31
lines changed

17 files changed

+299
-31
lines changed

compiler/rustc_hir/src/lang_items.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ language_item_table! {
314314
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;
315315

316316
IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
317-
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
318-
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
317+
318+
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
319+
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
320+
319321

320322
PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
321323

library/alloc/src/collections/vec_deque/iter.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,13 @@ unsafe impl<T> TrustedRandomAccess for Iter<'_, T> {}
211211
#[unstable(feature = "trusted_random_access", issue = "none")]
212212
unsafe impl<T> TrustedRandomAccessNoCoerce for Iter<'_, T> {
213213
const MAY_HAVE_SIDE_EFFECT: bool = false;
214+
const NEEDS_CLEANUP: bool = false;
215+
216+
fn cleanup(&mut self, num: usize, forward: bool) {
217+
if forward {
218+
let _ = self.advance_by(num);
219+
} else {
220+
let _ = self.advance_back_by(num);
221+
}
222+
}
214223
}

library/alloc/src/collections/vec_deque/iter_mut.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,13 @@ unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> {}
160160
#[unstable(feature = "trusted_random_access", issue = "none")]
161161
unsafe impl<T> TrustedRandomAccessNoCoerce for IterMut<'_, T> {
162162
const MAY_HAVE_SIDE_EFFECT: bool = false;
163+
const NEEDS_CLEANUP: bool = false;
164+
165+
fn cleanup(&mut self, num: usize, forward: bool) {
166+
if forward {
167+
let _ = self.advance_by(num);
168+
} else {
169+
let _ = self.advance_back_by(num);
170+
}
171+
}
163172
}

library/alloc/src/vec/in_place_collect.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ where
275275
drop_guard.dst = dst.add(1);
276276
}
277277
}
278+
// FIXME: this should run the TrustedRandomAccess cleanup code.
279+
// currently not running it is ok because IntoIter only implements TRA for Copy types
280+
// but if we relax that the cleanup will be needed
278281
mem::forget(drop_guard);
279282
len
280283
}

library/alloc/src/vec/into_iter.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,31 @@ where
291291
T: NonDrop,
292292
{
293293
const MAY_HAVE_SIDE_EFFECT: bool = false;
294+
const NEEDS_CLEANUP: bool = true;
295+
296+
fn cleanup(&mut self, num: usize, forward: bool) {
297+
if forward {
298+
if mem::size_of::<T>() == 0 {
299+
// SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound
300+
// effectively results in unsigned pointers representing positions 0..usize::MAX,
301+
// which is valid for ZSTs.
302+
self.ptr = unsafe { arith_offset(self.ptr as *const i8, num as isize) as *mut T }
303+
} else {
304+
// SAFETY: the caller must guarantee that `num` is in bounds
305+
self.ptr = unsafe { self.ptr.add(num) };
306+
}
307+
} else {
308+
if mem::size_of::<T>() == 0 {
309+
// SAFETY: same as above
310+
self.end = unsafe {
311+
arith_offset(self.end as *const i8, num.wrapping_neg() as isize) as *mut T
312+
}
313+
} else {
314+
// SAFETY: same as above
315+
self.end = unsafe { self.end.offset(num.wrapping_neg() as isize) };
316+
}
317+
}
318+
}
294319
}
295320

296321
#[cfg(not(no_global_oom_handling))]

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@ where
132132
I: TrustedRandomAccessNoCoerce,
133133
{
134134
const MAY_HAVE_SIDE_EFFECT: bool = true;
135+
136+
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
137+
138+
#[inline]
139+
fn cleanup(&mut self, num: usize, forward: bool) {
140+
self.it.cleanup(num, forward);
141+
}
135142
}
136143

137144
#[unstable(feature = "trusted_len", issue = "37572")]

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ where
158158
I: TrustedRandomAccessNoCoerce,
159159
{
160160
const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
161+
162+
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
163+
164+
#[inline]
165+
fn cleanup(&mut self, num: usize, forward: bool) {
166+
self.it.cleanup(num, forward);
167+
}
161168
}
162169

163170
#[stable(feature = "iter_copied", since = "1.36.0")]

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,13 @@ where
241241
I: TrustedRandomAccessNoCoerce,
242242
{
243243
const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
244+
245+
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
246+
247+
#[inline]
248+
fn cleanup(&mut self, num: usize, forward: bool) {
249+
self.iter.cleanup(num, forward);
250+
}
244251
}
245252

246253
#[stable(feature = "fused", since = "1.26.0")]

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,15 @@ where
231231
I: TrustedRandomAccessNoCoerce,
232232
{
233233
const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
234+
235+
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
236+
237+
#[inline]
238+
fn cleanup(&mut self, num: usize, forward: bool) {
239+
if let Some(iter) = self.iter.as_mut() {
240+
iter.cleanup(num, forward);
241+
}
242+
}
234243
}
235244

236245
/// Fuse specialization trait

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ where
199199
I: TrustedRandomAccessNoCoerce,
200200
{
201201
const MAY_HAVE_SIDE_EFFECT: bool = true;
202+
203+
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
204+
205+
#[inline]
206+
fn cleanup(&mut self, num: usize, forward: bool) {
207+
self.iter.cleanup(num, forward);
208+
}
202209
}
203210

204211
#[unstable(issue = "none", feature = "inplace_iteration")]

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,13 @@ where
400400
B: TrustedRandomAccessNoCoerce,
401401
{
402402
const MAY_HAVE_SIDE_EFFECT: bool = A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT;
403+
404+
const NEEDS_CLEANUP: bool = A::NEEDS_CLEANUP || B::NEEDS_CLEANUP;
405+
406+
fn cleanup(&mut self, num: usize, forward: bool) {
407+
self.a.cleanup(num, forward);
408+
self.b.cleanup(num, forward);
409+
}
403410
}
404411

405412
#[stable(feature = "fused", since = "1.26.0")]
@@ -542,9 +549,14 @@ pub unsafe trait TrustedRandomAccessNoCoerce: Sized {
542549
{
543550
self.size_hint().0
544551
}
552+
545553
/// `true` if getting an iterator element may have side effects.
546554
/// Remember to take inner iterators into account.
547555
const MAY_HAVE_SIDE_EFFECT: bool;
556+
557+
const NEEDS_CLEANUP: bool;
558+
559+
fn cleanup(&mut self, num: usize, forward: bool);
548560
}
549561

550562
/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to

library/core/src/iter/loop_desugar.rs

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,72 @@
1-
use crate::iter::IntoIterator as RealIntoIterator;
1+
use crate::iter::IntoIterator;
22
use crate::iter::TrustedRandomAccessNoCoerce;
33

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-
254
#[derive(Debug)]
265
#[doc(hidden)]
276
#[unstable(feature = "trusted_random_access", issue = "none")]
28-
pub struct ForLoopDesugar<I> {
7+
pub struct ForLoopDesugar<I: Iterator> {
298
iter: I,
309
idx: usize,
3110
}
3211

33-
#[unstable(feature = "trusted_random_access", issue = "none")]
34-
impl<I: Iterator> Iterator for ForLoopDesugar<I> {
35-
type Item = I::Item;
12+
impl<I: Iterator> ForLoopDesugar<I> {
13+
#[inline]
14+
#[cfg_attr(not(bootstrap), lang = "into_iter")]
15+
#[cfg_attr(bootstrap, allow(dead_code))]
16+
pub fn new(it: impl IntoIterator<Item = I::Item, IntoIter = I>) -> Self {
17+
let mut desugar = ForLoopDesugar { iter: it.into_iter(), idx: 0 };
18+
desugar.setup();
19+
desugar
20+
}
3621

3722
#[inline]
38-
fn next(&mut self) -> Option<I::Item> {
39-
// self.iter.next_spec(&mut self.idx)
23+
#[cfg_attr(not(bootstrap), lang = "next")]
24+
#[cfg_attr(bootstrap, allow(dead_code))]
25+
pub fn next(&mut self) -> Option<I::Item> {
4026
self.next_spec()
4127
}
4228
}
4329

30+
unsafe impl<#[may_dangle] I: Iterator> Drop for ForLoopDesugar<I> {
31+
#[inline]
32+
fn drop(&mut self) {
33+
self.cleanup();
34+
}
35+
}
36+
4437
trait DesugarSpec<T> {
38+
fn setup(&mut self);
39+
4540
fn next_spec(&mut self) -> Option<T>;
41+
42+
fn cleanup(&mut self);
4643
}
4744

4845
impl<I, T> DesugarSpec<T> for ForLoopDesugar<I>
4946
where
5047
I: Iterator<Item = T>,
5148
{
49+
#[inline]
50+
default fn setup(&mut self) {}
51+
5252
#[inline]
5353
default fn next_spec(&mut self) -> Option<I::Item> {
5454
self.iter.next()
5555
}
56+
57+
#[inline]
58+
default fn cleanup(&mut self) {}
5659
}
5760

5861
impl<I, T> DesugarSpec<T> for ForLoopDesugar<I>
5962
where
6063
I: TrustedRandomAccessNoCoerce + Iterator<Item = T>,
6164
{
65+
#[inline]
66+
fn setup(&mut self) {
67+
let _ = self.iter.advance_by(0);
68+
}
69+
6270
#[inline]
6371
fn next_spec(&mut self) -> Option<I::Item> {
6472
let idx = self.idx;
@@ -73,4 +81,11 @@ where
7381
None
7482
}
7583
}
84+
85+
#[inline]
86+
fn cleanup(&mut self) {
87+
if I::NEEDS_CLEANUP {
88+
self.iter.cleanup(self.idx, true);
89+
}
90+
}
7691
}

library/core/src/iter/range.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,18 @@ macro_rules! unsafe_range_trusted_random_access_impl {
502502
#[doc(hidden)]
503503
#[unstable(feature = "trusted_random_access", issue = "none")]
504504
unsafe impl TrustedRandomAccessNoCoerce for ops::Range<$t> {
505+
506+
fn cleanup(&mut self, num: usize, forward: bool) {
507+
if forward {
508+
let _ = self.advance_by(num);
509+
} else {
510+
let _ = self.advance_back_by(num);
511+
}
512+
}
513+
505514
const MAY_HAVE_SIDE_EFFECT: bool = false;
515+
516+
const NEEDS_CLEANUP: bool = false;
506517
}
507518
)*)
508519
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ pub trait Iterator {
9494
/// assert_eq!(None, iter.next());
9595
/// assert_eq!(None, iter.next());
9696
/// ```
97-
#[lang = "next"]
9897
#[stable(feature = "rust1", since = "1.0.0")]
98+
#[cfg_attr(bootstrap, lang = "next")]
9999
fn next(&mut self) -> Option<Self::Item>;
100100

101101
/// Returns the bounds on the remaining length of the iterator.

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
#![feature(deprecated_suggestion)]
175175
#![feature(doc_cfg)]
176176
#![feature(doc_notable_trait)]
177+
#![feature(dropck_eyepatch)]
177178
#![feature(rustdoc_internals)]
178179
#![feature(exhaustive_patterns)]
179180
#![feature(doc_cfg_hide)]

0 commit comments

Comments
 (0)