Use more associated types in core::iter.
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.
This commit is contained in:
parent
fed12499e7
commit
7bcf7fb500
@ -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 @@ impl<T, D, I> Iterator for Cloned<I> where
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, D, I> RandomAccessIterator for Cloned<I> where
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<It
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, A, B> RandomAccessIterator for Chain<A, B> where
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, U, A, B> Iterator for Zip<A, B> where
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
|
||||
}
|
||||
|
||||
#[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 @@ impl<T, U, A, B> RandomAccessIterator for Zip<A, B> where
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
|
25
src/test/run-pass/iter-cloned-type-inference.rs
Normal file
25
src/test/run-pass/iter-cloned-type-inference.rs
Normal file
@ -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]));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user