|
1 | 1 | use crate::fmt;
|
2 |
| -use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map}; |
| 2 | +use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; |
3 | 3 | use crate::ops::Try;
|
4 | 4 |
|
5 | 5 | /// An iterator that maps each element to an iterator, and yields the elements
|
@@ -114,6 +114,30 @@ where
|
114 | 114 | {
|
115 | 115 | }
|
116 | 116 |
|
| 117 | +#[unstable(feature = "trusted_len", issue = "37572")] |
| 118 | +unsafe impl<T, I, F, const N: usize> TrustedLen for FlatMap<I, [T; N], F> |
| 119 | +where |
| 120 | + I: TrustedLen, |
| 121 | + F: FnMut(I::Item) -> [T; N], |
| 122 | +{ |
| 123 | +} |
| 124 | + |
| 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 | + |
117 | 141 | /// An iterator that flattens one level of nesting in an iterator of things
|
118 | 142 | /// that can be turned into iterators.
|
119 | 143 | ///
|
@@ -230,6 +254,14 @@ where
|
230 | 254 | {
|
231 | 255 | }
|
232 | 256 |
|
| 257 | +#[unstable(feature = "trusted_len", issue = "37572")] |
| 258 | +unsafe impl<I> TrustedLen for Flatten<I> |
| 259 | +where |
| 260 | + I: TrustedLen, |
| 261 | + <I as Iterator>::Item: TrustedConstSize, |
| 262 | +{ |
| 263 | +} |
| 264 | + |
233 | 265 | /// Real logic of both `Flatten` and `FlatMap` which simply delegate to
|
234 | 266 | /// this type.
|
235 | 267 | #[derive(Clone, Debug)]
|
@@ -282,6 +314,17 @@ where
|
282 | 314 | let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
|
283 | 315 | let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
|
284 | 316 | let lo = flo.saturating_add(blo);
|
| 317 | + |
| 318 | + if let Some(fixed_size) = <<I as Iterator>::Item as ConstSizeIntoIterator>::size() { |
| 319 | + let (lower, upper) = self.iter.size_hint(); |
| 320 | + |
| 321 | + let lower = lower.saturating_mul(fixed_size).saturating_add(lo); |
| 322 | + let upper = |
| 323 | + try { fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?)? }; |
| 324 | + |
| 325 | + return (lower, upper); |
| 326 | + } |
| 327 | + |
285 | 328 | match (self.iter.size_hint(), fhi, bhi) {
|
286 | 329 | ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
|
287 | 330 | _ => (lo, None),
|
@@ -444,3 +487,52 @@ where
|
444 | 487 | init
|
445 | 488 | }
|
446 | 489 | }
|
| 490 | + |
| 491 | +trait ConstSizeIntoIterator: IntoIterator { |
| 492 | + // FIXME(#31844): convert to an associated const once specialization supports that |
| 493 | + fn size() -> Option<usize>; |
| 494 | +} |
| 495 | + |
| 496 | +impl<T> ConstSizeIntoIterator for T |
| 497 | +where |
| 498 | + T: IntoIterator, |
| 499 | +{ |
| 500 | + #[inline] |
| 501 | + default fn size() -> Option<usize> { |
| 502 | + None |
| 503 | + } |
| 504 | +} |
| 505 | + |
| 506 | +impl<T, const N: usize> ConstSizeIntoIterator for [T; N] { |
| 507 | + #[inline] |
| 508 | + fn size() -> Option<usize> { |
| 509 | + Some(N) |
| 510 | + } |
| 511 | +} |
| 512 | + |
| 513 | +impl<T, const N: usize> ConstSizeIntoIterator for &[T; N] { |
| 514 | + #[inline] |
| 515 | + fn size() -> Option<usize> { |
| 516 | + Some(N) |
| 517 | + } |
| 518 | +} |
| 519 | + |
| 520 | +impl<T, const N: usize> ConstSizeIntoIterator for &mut [T; N] { |
| 521 | + #[inline] |
| 522 | + fn size() -> Option<usize> { |
| 523 | + Some(N) |
| 524 | + } |
| 525 | +} |
| 526 | + |
| 527 | +#[doc(hidden)] |
| 528 | +#[unstable(feature = "std_internals", issue = "none")] |
| 529 | +// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<> |
| 530 | +// blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping |
| 531 | +pub unsafe trait TrustedConstSize: IntoIterator {} |
| 532 | + |
| 533 | +#[unstable(feature = "std_internals", issue = "none")] |
| 534 | +unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {} |
| 535 | +#[unstable(feature = "std_internals", issue = "none")] |
| 536 | +unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {} |
| 537 | +#[unstable(feature = "std_internals", issue = "none")] |
| 538 | +unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {} |
0 commit comments