]> git.lizzy.rs Git - rust.git/commitdiff
Use more associated types in core::iter.
authorHuon Wilson <dbau.pp+github@gmail.com>
Wed, 4 Mar 2015 10:32:33 +0000 (21:32 +1100)
committerHuon Wilson <dbau.pp+github@gmail.com>
Thu, 5 Mar 2015 11:50:09 +0000 (22:50 +1100)
This concretely improves type inference of some cases (see included
test). I assume the compiler struggles to reason about multiple layers
of generic type parameters (even with associated-type equalities) but
*can* understand pure associated types, since they are always directly
computable from the input types.

src/libcore/iter.rs
src/test/run-pass/iter-cloned-type-inference.rs [new file with mode: 0644]

index 9495bc2e19d6505638f763282adaa2752181c997..07203ad7d194ab09f97b3792d856fc5876cabd4f 100644 (file)
@@ -1279,14 +1279,14 @@ pub struct Cloned<I> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, D, I> Iterator for Cloned<I> where
-    T: Clone,
-    D: Deref<Target=T>,
-    I: Iterator<Item=D>,
+impl<I> Iterator for Cloned<I> where
+    I: Iterator,
+    I::Item: Deref,
+    <I::Item as Deref>::Target: Clone
 {
-    type Item = T;
+    type Item = <I::Item as Deref>::Target;
 
-    fn next(&mut self) -> Option<T> {
+    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
         self.it.next().cloned()
     }
 
@@ -1296,28 +1296,28 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, D, I> DoubleEndedIterator for Cloned<I> where
-    T: Clone,
-    D: Deref<Target=T>,
-    I: DoubleEndedIterator<Item=D>,
+impl<I> DoubleEndedIterator for Cloned<I> where
+    I: DoubleEndedIterator,
+    I::Item: Deref,
+    <I::Item as Deref>::Target: Clone
 {
-    fn next_back(&mut self) -> Option<T> {
+    fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
         self.it.next_back().cloned()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, D, I> ExactSizeIterator for Cloned<I> where
-    T: Clone,
-    D: Deref<Target=T>,
-    I: ExactSizeIterator<Item=D>,
+impl<I> ExactSizeIterator for Cloned<I> where
+    I: ExactSizeIterator,
+    I::Item: Deref,
+    <I::Item as Deref>::Target: Clone
 {}
 
 #[unstable(feature = "core", reason = "trait is experimental")]
-impl<T, D, I> RandomAccessIterator for Cloned<I> where
-    T: Clone,
-    D: Deref<Target=T>,
-    I: RandomAccessIterator<Item=D>
+impl<I> RandomAccessIterator for Cloned<I> where
+    I: RandomAccessIterator,
+    I::Item: Deref,
+    <I::Item as Deref>::Target: Clone
 {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1325,7 +1325,7 @@ fn indexable(&self) -> usize {
     }
 
     #[inline]
-    fn idx(&mut self, index: usize) -> Option<T> {
+    fn idx(&mut self, index: usize) -> Option<<Self as Iterator>::Item> {
         self.it.idx(index).cloned()
     }
 }
@@ -1400,11 +1400,14 @@ pub struct Chain<A, B> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<Item=T> {
-    type Item = T;
+impl<A, B> Iterator for Chain<A, B> where
+    A: Iterator,
+    B: Iterator<Item = A::Item>
+{
+    type Item = A::Item;
 
     #[inline]
-    fn next(&mut self) -> Option<T> {
+    fn next(&mut self) -> Option<A::Item> {
         if self.flag {
             self.b.next()
         } else {
@@ -1434,12 +1437,12 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
-    A: DoubleEndedIterator<Item=T>,
-    B: DoubleEndedIterator<Item=T>,
+impl<A, B> DoubleEndedIterator for Chain<A, B> where
+    A: DoubleEndedIterator,
+    B: DoubleEndedIterator<Item=A::Item>,
 {
     #[inline]
-    fn next_back(&mut self) -> Option<T> {
+    fn next_back(&mut self) -> Option<A::Item> {
         match self.b.next_back() {
             Some(x) => Some(x),
             None => self.a.next_back()
@@ -1448,9 +1451,9 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[unstable(feature = "core", reason = "trait is experimental")]
-impl<T, A, B> RandomAccessIterator for Chain<A, B> where
-    A: RandomAccessIterator<Item=T>,
-    B: RandomAccessIterator<Item=T>,
+impl<A, B> RandomAccessIterator for Chain<A, B> where
+    A: RandomAccessIterator,
+    B: RandomAccessIterator<Item = A::Item>,
 {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1459,7 +1462,7 @@ fn indexable(&self) -> usize {
     }
 
     #[inline]
-    fn idx(&mut self, index: usize) -> Option<T> {
+    fn idx(&mut self, index: usize) -> Option<A::Item> {
         let len = self.a.indexable();
         if index < len {
             self.a.idx(index)
@@ -1479,14 +1482,12 @@ pub struct Zip<A, B> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U, A, B> Iterator for Zip<A, B> where
-    A: Iterator<Item = T>,
-    B: Iterator<Item = U>,
+impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
 {
-    type Item = (T, U);
+    type Item = (A::Item, B::Item);
 
     #[inline]
-    fn next(&mut self) -> Option<(T, U)> {
+    fn next(&mut self) -> Option<(A::Item, B::Item)> {
         match self.a.next() {
             None => None,
             Some(x) => match self.b.next() {
@@ -1515,12 +1516,12 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
-    A: DoubleEndedIterator + ExactSizeIterator<Item=T>,
-    B: DoubleEndedIterator + ExactSizeIterator<Item=U>,
+impl<A, B> DoubleEndedIterator for Zip<A, B> where
+    A: DoubleEndedIterator + ExactSizeIterator,
+    B: DoubleEndedIterator + ExactSizeIterator,
 {
     #[inline]
-    fn next_back(&mut self) -> Option<(T, U)> {
+    fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
         let a_sz = self.a.len();
         let b_sz = self.b.len();
         if a_sz != b_sz {
@@ -1540,9 +1541,9 @@ fn next_back(&mut self) -> Option<(T, U)> {
 }
 
 #[unstable(feature = "core", reason = "trait is experimental")]
-impl<T, U, A, B> RandomAccessIterator for Zip<A, B> where
-    A: RandomAccessIterator<Item=T>,
-    B: RandomAccessIterator<Item=U>,
+impl<A, B> RandomAccessIterator for Zip<A, B> where
+    A: RandomAccessIterator,
+    B: RandomAccessIterator
 {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1550,7 +1551,7 @@ fn indexable(&self) -> usize {
     }
 
     #[inline]
-    fn idx(&mut self, index: usize) -> Option<(T, U)> {
+    fn idx(&mut self, index: usize) -> Option<(A::Item, B::Item)> {
         match self.a.idx(index) {
             None => None,
             Some(x) => match self.b.idx(index) {
@@ -2071,8 +2072,9 @@ pub struct Scan<I, St, F> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, I: Iterator<Item=A>, St, F> Iterator for Scan<I, St, F> where
-    F: FnMut(&mut St, A) -> Option<B>,
+impl<B, I, St, F> Iterator for Scan<I, St, F> where
+    I: Iterator,
+    F: FnMut(&mut St, I::Item) -> Option<B>,
 {
     type Item = B;
 
diff --git a/src/test/run-pass/iter-cloned-type-inference.rs b/src/test/run-pass/iter-cloned-type-inference.rs
new file mode 100644 (file)
index 0000000..6ce226b
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test to see that the element type of .cloned() can be inferred
+// properly. Previously this would fail to deduce the type of `sum`.
+
+#![feature(core)]
+
+use std::iter::AdditiveIterator;
+
+fn square_sum(v: &[i64]) -> i64 {
+    let sum = v.iter().cloned().sum();
+    sum * sum
+}
+
+fn main() {
+    assert_eq!(36, square_sum(&[1,2,3]));
+}