From ac557c29da5d4f6a436cb87b5ab41069d1709b50 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sun, 18 Sep 2022 22:47:35 -0400 Subject: [PATCH] make Fuse fuse all iterators --- library/core/src/iter/adapters/fuse.rs | 12 ++++++++++-- library/core/src/iter/traits/iterator.rs | 4 ---- library/core/src/iter/traits/marker.rs | 6 ++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index c931445420342..667b2845a77e0 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -15,7 +15,7 @@ use crate::ops::Try; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Fuse { - // NOTE: for `I: FusedIterator`, we never bother setting `None`, but + // NOTE: for `I: TrustedFusedIterator`, we never bother setting `None`, but // we still have to be prepared for that state due to variance. // See rust-lang/rust#85863 iter: Option, @@ -26,6 +26,14 @@ impl Fuse { } } +// Safety: only implemented by core::iter::Fuse to specialize on nested Fuse> +#[rustc_unsafe_specialization_marker] +unsafe trait TrustedFusedIterator: Iterator {} + +// Fuse properly fuses iterators when it's specialized on this trait +// only if that specialization is correct is this impl correct +unsafe impl TrustedFusedIterator for Fuse where I: Iterator {} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Fuse where I: Iterator {} @@ -330,7 +338,7 @@ where #[doc(hidden)] impl FuseImpl for Fuse where - I: FusedIterator, + I: TrustedFusedIterator, { #[inline] fn next(&mut self) -> Option<::Item> { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b2d08f4b0f67b..fe8477f287a81 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1543,10 +1543,6 @@ pub trait Iterator { /// [`Some(T)`] again. `fuse()` adapts an iterator, ensuring that after a /// [`None`] is given, it will always return [`None`] forever. /// - /// Note that the [`Fuse`] wrapper is a no-op on iterators that implement - /// the [`FusedIterator`] trait. `fuse()` may therefore behave incorrectly - /// if the [`FusedIterator`] trait is improperly implemented. - /// /// [`Some(T)`]: Some /// [`FusedIterator`]: crate::iter::FusedIterator /// diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index da753745740d7..f3d0dac436a34 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -3,17 +3,15 @@ use crate::iter::Step; /// An iterator that always continues to yield `None` when exhausted. /// /// Calling next on a fused iterator that has returned `None` once is guaranteed -/// to return [`None`] again. This trait should be implemented by all iterators -/// that behave this way because it allows optimizing [`Iterator::fuse()`]. +/// to return [`None`] again. /// /// Note: In general, you should not use `FusedIterator` in generic bounds if /// you need a fused iterator. Instead, you should just call [`Iterator::fuse()`] -/// on the iterator. If the iterator is already fused, the additional [`Fuse`] +/// on the iterator. If the iterator is already a [`Fuse`], the additional [`Fuse`] /// wrapper will be a no-op with no performance penalty. /// /// [`Fuse`]: crate::iter::Fuse #[stable(feature = "fused", since = "1.26.0")] -#[rustc_unsafe_specialization_marker] pub trait FusedIterator: Iterator {} #[stable(feature = "fused", since = "1.26.0")]