about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-08-15 04:24:29 +0000
committerbors <bors@rust-lang.org>2019-08-15 04:24:29 +0000
commit1cdcea920e56a5d0587307a4c9cf8fff5c77c4bc (patch)
treeccb6b9be0ea3d973f4e0808ef6f7c11bebf52a9b /src/test
parent9e9a136fcec5eb78f09a14dfd072a51ae2550269 (diff)
parentbca6f28f7f7a6db3416c0d4e631a7a4cc1072cf7 (diff)
downloadrust-1cdcea920e56a5d0587307a4c9cf8fff5c77c4bc.tar.gz
rust-1cdcea920e56a5d0587307a4c9cf8fff5c77c4bc.zip
Auto merge of #62429 - cuviper:iter-closures, r=cramertj
Reduce the genericity of closures in the iterator traits

By default, closures inherit the generic parameters of their scope,
including `Self`. However, in most cases, the closures used to implement
iterators don't need to be generic on the iterator type, only its `Item`
type. We can reduce this genericity by redirecting such closures through
local functions.

This does make the closures more cumbersome to write, but it will
hopefully reduce duplication in their monomorphizations, as well as
their related type lengths.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/codegen/iter-fold-closure-no-dupes.rs14
-rw-r--r--src/test/codegen/iter-fold-closure-no-iterator.rs10
-rw-r--r--src/test/ui/iterators/iter-count-overflow-debug.rs16
-rw-r--r--src/test/ui/iterators/iter-count-overflow-ndebug.rs11
-rw-r--r--src/test/ui/iterators/iter-map-fold-type-length.rs38
-rw-r--r--src/test/ui/iterators/iter-position-overflow-debug.rs22
-rw-r--r--src/test/ui/iterators/iter-position-overflow-ndebug.rs13
7 files changed, 124 insertions, 0 deletions
diff --git a/src/test/codegen/iter-fold-closure-no-dupes.rs b/src/test/codegen/iter-fold-closure-no-dupes.rs
new file mode 100644
index 00000000000..ec58f7068ab
--- /dev/null
+++ b/src/test/codegen/iter-fold-closure-no-dupes.rs
@@ -0,0 +1,14 @@
+//! Check that fold closures aren't duplicated for each iterator type.
+// compile-flags: -C opt-level=0
+
+fn main() {
+    (0i32..10).by_ref().count();
+    (0i32..=10).by_ref().count();
+}
+
+// `count` calls `fold`, which calls `try_fold` -- find the `fold` closure:
+// CHECK: {{^define.*Iterator::fold::.*closure}}
+//
+// Only one closure is needed for both `count` calls, even from different
+// monomorphized iterator types, as it's only generic over the item type.
+// CHECK-NOT: {{^define.*Iterator::fold::.*closure}}
diff --git a/src/test/codegen/iter-fold-closure-no-iterator.rs b/src/test/codegen/iter-fold-closure-no-iterator.rs
new file mode 100644
index 00000000000..fbeafd5f395
--- /dev/null
+++ b/src/test/codegen/iter-fold-closure-no-iterator.rs
@@ -0,0 +1,10 @@
+//! Check that fold closures aren't generic in the iterator type.
+// compile-flags: -C opt-level=0
+
+fn main() {
+    (0i32..10).by_ref().count();
+}
+
+// `count` calls `fold`, which calls `try_fold` -- that `fold` closure should
+// not be generic in the iterator type, only in the item type.
+// CHECK-NOT: {{^define.*Iterator::fold::.*closure.*Range}}
diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs
new file mode 100644
index 00000000000..d6612035750
--- /dev/null
+++ b/src/test/ui/iterators/iter-count-overflow-debug.rs
@@ -0,0 +1,16 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// ignore-wasm32-bare compiled with panic=abort by default
+// compile-flags: -C debug_assertions=yes -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    assert_eq!((0..MAX).by_ref().count(), MAX);
+
+    let r = panic::catch_unwind(|| {
+        (0..=MAX).by_ref().count()
+    });
+    assert!(r.is_err());
+}
diff --git a/src/test/ui/iterators/iter-count-overflow-ndebug.rs b/src/test/ui/iterators/iter-count-overflow-ndebug.rs
new file mode 100644
index 00000000000..b755bb554f4
--- /dev/null
+++ b/src/test/ui/iterators/iter-count-overflow-ndebug.rs
@@ -0,0 +1,11 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// compile-flags: -C debug_assertions=no -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    assert_eq!((0..MAX).by_ref().count(), MAX);
+    assert_eq!((0..=MAX).by_ref().count(), 0);
+}
diff --git a/src/test/ui/iterators/iter-map-fold-type-length.rs b/src/test/ui/iterators/iter-map-fold-type-length.rs
new file mode 100644
index 00000000000..8ce4fcd8731
--- /dev/null
+++ b/src/test/ui/iterators/iter-map-fold-type-length.rs
@@ -0,0 +1,38 @@
+// run-pass
+//! Check that type lengths don't explode with `Map` folds.
+//!
+//! The normal limit is a million, and this test used to exceed 1.5 million, but
+//! now we can survive an even tighter limit. Still seems excessive though...
+#![type_length_limit = "256000"]
+
+// Custom wrapper so Iterator methods aren't specialized.
+struct Iter<I>(I);
+
+impl<I> Iterator for Iter<I>
+where
+    I: Iterator
+{
+    type Item = I::Item;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    let c = Iter(0i32..10)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .map(|x| x)
+        .count();
+    assert_eq!(c, 10);
+}
diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs
new file mode 100644
index 00000000000..f1eded31702
--- /dev/null
+++ b/src/test/ui/iterators/iter-position-overflow-debug.rs
@@ -0,0 +1,22 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// ignore-wasm32-bare compiled with panic=abort by default
+// compile-flags: -C debug_assertions=yes -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    let n = MAX as u64;
+    assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX));
+
+    let r = panic::catch_unwind(|| {
+        (0..).by_ref().position(|i| i > n)
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        (0..=n + 1).by_ref().position(|_| false)
+    });
+    assert!(r.is_err());
+}
diff --git a/src/test/ui/iterators/iter-position-overflow-ndebug.rs b/src/test/ui/iterators/iter-position-overflow-ndebug.rs
new file mode 100644
index 00000000000..368f9c0c02b
--- /dev/null
+++ b/src/test/ui/iterators/iter-position-overflow-ndebug.rs
@@ -0,0 +1,13 @@
+// run-pass
+// only-32bit too impatient for 2⁶⁴ items
+// compile-flags: -C debug_assertions=no -C opt-level=3
+
+use std::panic;
+use std::usize::MAX;
+
+fn main() {
+    let n = MAX as u64;
+    assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX));
+    assert_eq!((0..).by_ref().position(|i| i > n), Some(0));
+    assert_eq!((0..=n + 1).by_ref().position(|_| false), None);
+}