From a1809d57840a19e28e93b437a7d029be3656acb8 Mon Sep 17 00:00:00 2001 From: oberien Date: Thu, 18 Jan 2018 18:40:08 +0100 Subject: [PATCH 1/3] Implement TrustedLen for Take and Take --- src/libcore/iter/mod.rs | 3 +++ src/libcore/iter/range.rs | 3 +++ src/libcore/iter/sources.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 7314fac282b66..bf8367d85fd10 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -2322,6 +2322,9 @@ impl ExactSizeIterator for Take where I: ExactSizeIterator {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Take where I: FusedIterator {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Take {} + /// An iterator to maintain state while iterating another iterator. /// /// This `struct` is created by the [`scan`] method on [`Iterator`]. See its diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 66a76a24df45a..5af6df3e1cb47 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -325,6 +325,9 @@ impl Iterator for ops::RangeFrom { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for ops::RangeFrom {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::RangeFrom {} + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl Iterator for ops::RangeInclusive { type Item = A; diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index b405f35d5e4db..b05a893e66104 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -44,6 +44,9 @@ impl DoubleEndedIterator for Repeat { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Repeat {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Repeat {} + /// Creates a new iterator that endlessly repeats a single element. /// /// The `repeat()` function repeats a single value over and over and over and From 75474ff1323c2968bb2dafc8b8f0af4817a89d01 Mon Sep 17 00:00:00 2001 From: oberien Date: Fri, 2 Feb 2018 09:31:56 +0100 Subject: [PATCH 2/3] TrustedLen for Repeat / RangeFrom test cases --- src/libcore/tests/iter.rs | 43 ++++++++++++++++++++++++++ src/test/codegen/repeat-trusted-len.rs | 23 ++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/test/codegen/repeat-trusted-len.rs diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index e52e119ff59b9..f6b12fbb2dd11 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1371,6 +1371,29 @@ fn test_range_from_nth() { assert_eq!(r, 16..); assert_eq!(r.nth(10), Some(26)); assert_eq!(r, 27..); + + assert_eq!((0..).size_hint(), (usize::MAX, None)); +} + +fn is_trusted_len(_: I) {} + +#[test] +fn test_range_from_take() { + let mut it = (0..).take(3); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.next(), Some(2)); + assert_eq!(it.next(), None); + is_trusted_len((0..).take(3)); + assert_eq!((0..).take(3).size_hint(), (3, Some(3))); + assert_eq!((0..).take(0).size_hint(), (0, Some(0))); + assert_eq!((0..).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); +} + +#[test] +fn test_range_from_take_collect() { + let v: Vec<_> = (0..).take(3).collect(); + assert_eq!(v, vec![0, 1, 2]); } #[test] @@ -1465,6 +1488,26 @@ fn test_repeat() { assert_eq!(it.next(), Some(42)); assert_eq!(it.next(), Some(42)); assert_eq!(it.next(), Some(42)); + assert_eq!(repeat(42).size_hint(), (usize::MAX, None)); +} + +#[test] +fn test_repeat_take() { + let mut it = repeat(42).take(3); + assert_eq!(it.next(), Some(42)); + assert_eq!(it.next(), Some(42)); + assert_eq!(it.next(), Some(42)); + assert_eq!(it.next(), None); + is_trusted_len(repeat(42).take(3)); + assert_eq!(repeat(42).take(3).size_hint(), (3, Some(3))); + assert_eq!(repeat(42).take(0).size_hint(), (0, Some(0))); + assert_eq!(repeat(42).take(usize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); +} + +#[test] +fn test_repeat_take_collect() { + let v: Vec<_> = repeat(42).take(3).collect(); + assert_eq!(v, vec![42, 42, 42]); } #[test] diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs new file mode 100644 index 0000000000000..43872f15d51e2 --- /dev/null +++ b/src/test/codegen/repeat-trusted-len.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -O +// ignore-tidy-linelength + +#![crate_type = "lib"] + +use std::iter; + +// CHECK-LABEL: @repeat_take_collect +#[no_mangle] +pub fn repeat_take_collect() -> Vec { +// CHECK: call void @llvm.memset.p0i8 + iter::repeat(42).take(100000).collect() +} From 6caec2c0494a173f696e5a63583ff35d1bd106aa Mon Sep 17 00:00:00 2001 From: oberien Date: Sun, 4 Feb 2018 16:04:06 +0100 Subject: [PATCH 3/3] Document TrustedLen guarantees more explicitly --- src/libcore/iter/traits.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 11e668d228c48..be4889f24877c 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -970,9 +970,11 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} /// The iterator reports a size hint where it is either exact /// (lower bound is equal to upper bound), or the upper bound is [`None`]. /// The upper bound must only be [`None`] if the actual iterator length is -/// larger than [`usize::MAX`]. +/// larger than [`usize::MAX`]. In that case, the lower bound must be +/// [`usize::MAX`], resulting in a [`.size_hint`] of `(usize::MAX, None)`. /// -/// The iterator must produce exactly the number of elements it reported. +/// The iterator must produce exactly the number of elements it reported +/// or diverge before reaching the end. /// /// # Safety ///