Skip to content

Commit 8dd903c

Browse files
committed
implement ConstSizeIntoIterator for &[T;N] in addition to [T;N]
Due to #20400 the corresponding TrustedLen impls need a helper trait instead of directly adding `Item = &[T;N]` bounds. Since TrustedLen is a public trait this in turn means the helper trait needs to be public. Since it's just a workaround for a compiler deficit it's marked hidden, unstable and unsafe.
1 parent 18a034f commit 8dd903c

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

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

+52-3
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ where
122122
{
123123
}
124124

125+
#[unstable(feature = "trusted_len", issue = "37572")]
126+
unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a [T; N], F>
127+
where
128+
I: TrustedLen,
129+
F: FnMut(I::Item) -> &'a [T; N],
130+
{
131+
}
132+
133+
#[unstable(feature = "trusted_len", issue = "37572")]
134+
unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a mut [T; N], F>
135+
where
136+
I: TrustedLen,
137+
F: FnMut(I::Item) -> &'a mut [T; N],
138+
{
139+
}
140+
125141
/// An iterator that flattens one level of nesting in an iterator of things
126142
/// that can be turned into iterators.
127143
///
@@ -239,8 +255,10 @@ where
239255
}
240256

241257
#[unstable(feature = "trusted_len", issue = "37572")]
242-
unsafe impl<T, I, const N: usize> TrustedLen for Flatten<I> where
243-
I: Iterator<Item = [T; N]> + TrustedLen
258+
unsafe impl<I> TrustedLen for Flatten<I>
259+
where
260+
I: TrustedLen,
261+
<I as Iterator>::Item: TrustedConstSize,
244262
{
245263
}
246264

@@ -475,10 +493,14 @@ where
475493
}
476494

477495
trait ConstSizeIntoIterator: IntoIterator {
496+
// FIXME(#31844): convert to an associated const once specialization supports that
478497
fn size() -> Option<usize>;
479498
}
480499

481-
impl<T> ConstSizeIntoIterator for T where T: IntoIterator {
500+
impl<T> ConstSizeIntoIterator for T
501+
where
502+
T: IntoIterator,
503+
{
482504
#[inline]
483505
default fn size() -> Option<usize> {
484506
None
@@ -491,3 +513,30 @@ impl<T, const N: usize> ConstSizeIntoIterator for [T; N] {
491513
Some(N)
492514
}
493515
}
516+
517+
impl<T, const N: usize> ConstSizeIntoIterator for &[T; N] {
518+
#[inline]
519+
fn size() -> Option<usize> {
520+
Some(N)
521+
}
522+
}
523+
524+
impl<T, const N: usize> ConstSizeIntoIterator for &mut [T; N] {
525+
#[inline]
526+
fn size() -> Option<usize> {
527+
Some(N)
528+
}
529+
}
530+
531+
#[doc(hidden)]
532+
#[unstable(feature = "std_internals", issue = "none")]
533+
// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<>
534+
// blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping
535+
pub unsafe trait TrustedConstSize: IntoIterator {}
536+
537+
#[unstable(feature = "std_internals", issue = "none")]
538+
unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {}
539+
#[unstable(feature = "std_internals", issue = "none")]
540+
unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {}
541+
#[unstable(feature = "std_internals", issue = "none")]
542+
unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {}

library/core/tests/iter/adapters/flatten.rs

+16
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,23 @@ fn test_trusted_len_flatten() {
129129
let iter = array::IntoIter::new([[(); usize::MAX]; 2]).flatten();
130130
assert_eq!(iter.size_hint(), (usize::MAX, None));
131131

132+
let mut a = [(); 10];
133+
let mut b = [(); 10];
134+
135+
let iter = array::IntoIter::new([&mut a, &mut b]).flatten();
136+
assert_trusted_len(&iter);
137+
assert_eq!(iter.size_hint(), (20, Some(20)));
138+
core::mem::drop(iter);
139+
140+
let iter = array::IntoIter::new([&a, &b]).flatten();
141+
assert_trusted_len(&iter);
142+
assert_eq!(iter.size_hint(), (20, Some(20)));
143+
132144
let iter = [(), (), ()].iter().flat_map(|_| [(); 1000]);
133145
assert_trusted_len(&iter);
134146
assert_eq!(iter.size_hint(), (3000, Some(3000)));
147+
148+
let iter = [(), ()].iter().flat_map(|_| &a);
149+
assert_trusted_len(&iter);
150+
assert_eq!(iter.size_hint(), (20, Some(20)));
135151
}

0 commit comments

Comments
 (0)