Skip to content

Commit ac557c2

Browse files
committed
make Fuse fuse all iterators
1 parent a37499a commit ac557c2

File tree

3 files changed

+12
-10
lines changed

3 files changed

+12
-10
lines changed

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::ops::Try;
1515
#[must_use = "iterators are lazy and do nothing unless consumed"]
1616
#[stable(feature = "rust1", since = "1.0.0")]
1717
pub struct Fuse<I> {
18-
// NOTE: for `I: FusedIterator`, we never bother setting `None`, but
18+
// NOTE: for `I: TrustedFusedIterator`, we never bother setting `None`, but
1919
// we still have to be prepared for that state due to variance.
2020
// See rust-lang/rust#85863
2121
iter: Option<I>,
@@ -26,6 +26,14 @@ impl<I> Fuse<I> {
2626
}
2727
}
2828

29+
// Safety: only implemented by core::iter::Fuse to specialize on nested Fuse<Fuse<...>>
30+
#[rustc_unsafe_specialization_marker]
31+
unsafe trait TrustedFusedIterator: Iterator {}
32+
33+
// Fuse properly fuses iterators when it's specialized on this trait
34+
// only if that specialization is correct is this impl correct
35+
unsafe impl<I> TrustedFusedIterator for Fuse<I> where I: Iterator {}
36+
2937
#[stable(feature = "fused", since = "1.26.0")]
3038
impl<I> FusedIterator for Fuse<I> where I: Iterator {}
3139

@@ -330,7 +338,7 @@ where
330338
#[doc(hidden)]
331339
impl<I> FuseImpl<I> for Fuse<I>
332340
where
333-
I: FusedIterator,
341+
I: TrustedFusedIterator,
334342
{
335343
#[inline]
336344
fn next(&mut self) -> Option<<I as Iterator>::Item> {

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,10 +1543,6 @@ pub trait Iterator {
15431543
/// [`Some(T)`] again. `fuse()` adapts an iterator, ensuring that after a
15441544
/// [`None`] is given, it will always return [`None`] forever.
15451545
///
1546-
/// Note that the [`Fuse`] wrapper is a no-op on iterators that implement
1547-
/// the [`FusedIterator`] trait. `fuse()` may therefore behave incorrectly
1548-
/// if the [`FusedIterator`] trait is improperly implemented.
1549-
///
15501546
/// [`Some(T)`]: Some
15511547
/// [`FusedIterator`]: crate::iter::FusedIterator
15521548
///

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ use crate::iter::Step;
33
/// An iterator that always continues to yield `None` when exhausted.
44
///
55
/// Calling next on a fused iterator that has returned `None` once is guaranteed
6-
/// to return [`None`] again. This trait should be implemented by all iterators
7-
/// that behave this way because it allows optimizing [`Iterator::fuse()`].
6+
/// to return [`None`] again.
87
///
98
/// Note: In general, you should not use `FusedIterator` in generic bounds if
109
/// you need a fused iterator. Instead, you should just call [`Iterator::fuse()`]
11-
/// on the iterator. If the iterator is already fused, the additional [`Fuse`]
10+
/// on the iterator. If the iterator is already a [`Fuse`], the additional [`Fuse`]
1211
/// wrapper will be a no-op with no performance penalty.
1312
///
1413
/// [`Fuse`]: crate::iter::Fuse
1514
#[stable(feature = "fused", since = "1.26.0")]
16-
#[rustc_unsafe_specialization_marker]
1715
pub trait FusedIterator: Iterator {}
1816

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

0 commit comments

Comments
 (0)