Rollup merge of #149597 - jdonszelmann:revert-iterator-exactly-one, r=wafflelapkin

Revert "implement and test `Iterator::{exactly_one, collect_array}`"

This reverts https://github.com/rust-lang/rust/pull/149270

I was quite excited it merged, and immediately realized with ``@WaffleLapkin`` that this is a breaking change on nightly! Despite still being marked as unstable, the name conflicts with the name on itertools as was discussed on the PR itself: https://github.com/rust-lang/rust/pull/149270#issuecomment-3573812447.

I'll reopen the PR though, and mark it as blocked on https://github.com/rust-lang/rust/pull/148605
This commit is contained in:
Matthias Krüger 2025-12-04 09:22:14 +01:00 committed by GitHub
commit c598b4e300
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 10 additions and 72 deletions

View file

@ -86,8 +86,7 @@ impl MetadataLoader for DefaultMetadataLoader {
format!("failed to parse aix dylib '{}': {}", path.display(), e)
})?;
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
match Itertools::exactly_one(archive.members()) {
match archive.members().exactly_one() {
Ok(lib) => {
let lib = lib.map_err(|e| {
format!("failed to parse aix dylib '{}': {}", path.display(), e)

View file

@ -4034,62 +4034,6 @@ pub trait Iterator {
{
unreachable!("Always specialized");
}
/// Checks if the iterator contains *exactly* one element.
/// If so, returns this one element.
///
/// See also [`collect_array`](Iterator::collect_array) for lengths other than `1`.
///
/// # Examples
///
/// ```
/// #![feature(exact_length_collection)]
///
/// assert_eq!([1].into_iter().exactly_one(), Some(1));
/// assert_eq!([].into_iter().exactly_one(), None::<()>);
///
/// // There is exactly one even integer in the array:
/// assert_eq!([1, 2, 3].into_iter().filter(|x| x % 2 == 0).exactly_one(), Some(2));
/// // But there are two odds, which is too many:
/// assert_eq!([1, 2, 3].into_iter().filter(|x| x % 2 == 1).exactly_one(), None);
/// ```
#[inline]
#[unstable(feature = "exact_length_collection", issue = "149266")]
fn exactly_one(self) -> Option<Self::Item>
where
Self: Sized,
{
self.collect_array::<1>().map(|[i]| i)
}
/// Checks if an iterator has *exactly* `N` elements.
/// If so, returns those `N` elements in an array.
///
/// See also [`exactly_one`](Iterator::exactly_one) when expecting a single element.
///
/// # Examples
///
/// ```
/// #![feature(exact_length_collection)]
///
/// assert_eq!([1, 2, 3, 4].into_iter().collect_array(), Some([1, 2, 3, 4]));
/// assert_eq!([1, 2].into_iter().chain([3, 4]).collect_array(), Some([1, 2, 3, 4]));
///
/// // Iterator contains too few elements:
/// assert_eq!([1, 2].into_iter().collect_array::<4>(), None);
/// // Iterator contains too many elements:
/// assert_eq!([1, 2, 3, 4, 5].into_iter().collect_array::<4>(), None);
/// // Taking 4 makes it work again:
/// assert_eq!([1, 2, 3, 4, 5].into_iter().take(4).collect_array(), Some([1, 2, 3, 4]));
/// ```
#[inline]
#[unstable(feature = "exact_length_collection", issue = "149266")]
fn collect_array<const N: usize>(mut self) -> Option<[Self::Item; N]>
where
Self: Sized,
{
self.next_chunk().ok().filter(|_| self.next().is_none())
}
}
trait SpecIterEq<B: Iterator>: Iterator {

View file

@ -1126,8 +1126,7 @@ pub(crate) fn print_impl(
}
if impl_.kind.is_fake_variadic()
&& let Some(generics) = ty.generics()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
&& let Ok(inner_type) = Itertools::exactly_one(generics)
&& let Ok(inner_type) = generics.exactly_one()
{
let last = ty.last();
if f.alternate() {
@ -1207,8 +1206,7 @@ impl clean::Impl {
}
} else if let clean::Type::Path { path } = type_
&& let Some(generics) = path.generics()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
&& let Ok(ty) = Itertools::exactly_one(generics)
&& let Ok(ty) = generics.exactly_one()
&& self.kind.is_fake_variadic()
{
print_anchor(path.def_id(), path.last(), cx).fmt(f)?;

View file

@ -92,8 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
(matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
.then_some((v.def_id, v.span))
});
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
if let Ok((id, span)) = Itertools::exactly_one(iter)
if let Ok((id, span)) = iter.exactly_one()
&& !find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(..))
{
self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
@ -105,8 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
.iter()
.filter(|field| !cx.effective_visibilities.is_exported(field.def_id));
if fields.len() > 1
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
&& let Ok(field) = Itertools::exactly_one(private_fields)
&& let Ok(field) = private_fields.exactly_one()
&& let TyKind::Tup([]) = field.ty.kind
{
span_lint_and_then(

View file

@ -4,7 +4,7 @@ use std::mem::MaybeUninit;
trait CollectSlice<'a>: Iterator {
fn inner_array<const N: usize>(&mut self) -> [Self::Item; N];
fn custom_collect_array<const N: usize>(&mut self) -> [Self::Item; N] {
fn collect_array<const N: usize>(&mut self) -> [Self::Item; N] {
let result = self.inner_array();
assert!(self.next().is_none());
result
@ -34,5 +34,5 @@ where
fn main() {
let mut foos = [0u64; 9].iter().cloned();
let _bar: [u64; 9] = foos.custom_collect_array::<9_usize>();
let _bar: [u64; 9] = foos.collect_array::<9_usize>();
}

View file

@ -29,11 +29,10 @@ where
fn main() {
assert_eq!(
CollectArray::collect_array(
&mut [[1, 2], [3, 4]]
[[1, 2], [3, 4]]
.iter()
.map(|row| CollectArray::collect_array(&mut row.iter()))
),
.map(|row| row.iter().collect_array())
.collect_array(),
[[&1, &2], [&3, &4]]
);
}