Skip to content

Commit f50da06

Browse files
Rollup merge of #140985 - zachs18:fuse-default-some, r=tgross35
Change `core::iter::Fuse`'s `Default` impl to do what its docs say it does The [docs on `impl<I: Default> Default for core::iter::Fuse<I>`](https://doc.rust-lang.org/nightly/std/iter/struct.Fuse.html#impl-Default-for-Fuse%3CI%3E) say (as the `I: Default` bound implies) that `Fuse::<I>::default` "Creates a `Fuse` iterator from the default value of `I`". However, the implementation creates a `Fuse` with `Fuse { iter: Default::default() }`, and since the `iter` field is an `Option<I>`, this is actually `Fuse { iter: None }`, not `Fuse { iter: Some(I::default()) }`, so `Fuse::<I>::default()` always returns an empty iterator, even if `I::default()` would not be empty. This PR changes `Fuse`'s `Default` implementation to match the documentation. This will be a behavior change for anyone currently using `Fuse::<I>::default()` where `I::default()` is not an empty iterator[^1], as `Fuse::<I>::default()` will now also not be an empty iterator. (Alternately, the docs could be updated to reflect what the current implementation actually does, i.e. returns an always-exhausted iterator that never yields any items (even if `I::default()` would have yielded items). With this option, the `I: Default` bound could also be removed to reflect that no `I` is ever created.) [Current behavior example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=a1e0adc4badca3dc11bfb70a99213249) (maybe an example like this should be added to the docs either way?) This PR changes publicly observable behavior, so I think requires at least a T-libs-api FCP? r? libs-api cc #140961 `impl<I: Default> Default for Fuse<I>` was added in 1.70.0 (#99929), and it's docs and behavior do not appear to have changed since (`Fuse`'s `iter` field has been an `Option` since before the impl was added). [^1]: IIUC it is a "de facto" guideline for the stdlib that an iterator type's `default()` should be empty (and for iterators where that would not make sense, they should not implement `Default`): cc rust-lang/libs-team#77 (comment) , so for stdlib iterators, I don't think this would change anything. However, if a user has a custom `Iterator` type `I`, *and* they are using `Fuse<I>`, *and* they call `Fuse::<I>::default()`, this may change the behavior of their code.
2 parents 706f244 + f3d4278 commit f50da06

File tree

1 file changed

+23
-1
lines changed
  • library/core/src/iter/adapters

1 file changed

+23
-1
lines changed

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,30 @@ impl<I: Default> Default for Fuse<I> {
198198
/// let iter: Fuse<slice::Iter<'_, u8>> = Default::default();
199199
/// assert_eq!(iter.len(), 0);
200200
/// ```
201+
///
202+
/// This is equivalent to `I::default().fuse()`[^fuse_note]; e.g. if
203+
/// `I::default()` is not an empty iterator, then this will not be
204+
/// an empty iterator.
205+
///
206+
/// ```
207+
/// # use std::iter::Fuse;
208+
/// #[derive(Default)]
209+
/// struct Fourever;
210+
///
211+
/// impl Iterator for Fourever {
212+
/// type Item = u32;
213+
/// fn next(&mut self) -> Option<u32> {
214+
/// Some(4)
215+
/// }
216+
/// }
217+
///
218+
/// let mut iter: Fuse<Fourever> = Default::default();
219+
/// assert_eq!(iter.next(), Some(4));
220+
/// ```
221+
///
222+
/// [^fuse_note]: if `I` does not override `Iterator::fuse`'s default implementation
201223
fn default() -> Self {
202-
Fuse { iter: Default::default() }
224+
Fuse { iter: Some(I::default()) }
203225
}
204226
}
205227

0 commit comments

Comments
 (0)