Skip to content

Commit 7bcf7fb

Browse files
committed
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.
1 parent fed1249 commit 7bcf7fb

File tree

2 files changed

+73
-46
lines changed

2 files changed

+73
-46
lines changed

src/libcore/iter.rs

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,14 +1279,14 @@ pub struct Cloned<I> {
12791279
}
12801280

12811281
#[stable(feature = "rust1", since = "1.0.0")]
1282-
impl<T, D, I> Iterator for Cloned<I> where
1283-
T: Clone,
1284-
D: Deref<Target=T>,
1285-
I: Iterator<Item=D>,
1282+
impl<I> Iterator for Cloned<I> where
1283+
I: Iterator,
1284+
I::Item: Deref,
1285+
<I::Item as Deref>::Target: Clone
12861286
{
1287-
type Item = T;
1287+
type Item = <I::Item as Deref>::Target;
12881288

1289-
fn next(&mut self) -> Option<T> {
1289+
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
12901290
self.it.next().cloned()
12911291
}
12921292

@@ -1296,36 +1296,36 @@ impl<T, D, I> Iterator for Cloned<I> where
12961296
}
12971297

12981298
#[stable(feature = "rust1", since = "1.0.0")]
1299-
impl<T, D, I> DoubleEndedIterator for Cloned<I> where
1300-
T: Clone,
1301-
D: Deref<Target=T>,
1302-
I: DoubleEndedIterator<Item=D>,
1299+
impl<I> DoubleEndedIterator for Cloned<I> where
1300+
I: DoubleEndedIterator,
1301+
I::Item: Deref,
1302+
<I::Item as Deref>::Target: Clone
13031303
{
1304-
fn next_back(&mut self) -> Option<T> {
1304+
fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
13051305
self.it.next_back().cloned()
13061306
}
13071307
}
13081308

13091309
#[stable(feature = "rust1", since = "1.0.0")]
1310-
impl<T, D, I> ExactSizeIterator for Cloned<I> where
1311-
T: Clone,
1312-
D: Deref<Target=T>,
1313-
I: ExactSizeIterator<Item=D>,
1310+
impl<I> ExactSizeIterator for Cloned<I> where
1311+
I: ExactSizeIterator,
1312+
I::Item: Deref,
1313+
<I::Item as Deref>::Target: Clone
13141314
{}
13151315

13161316
#[unstable(feature = "core", reason = "trait is experimental")]
1317-
impl<T, D, I> RandomAccessIterator for Cloned<I> where
1318-
T: Clone,
1319-
D: Deref<Target=T>,
1320-
I: RandomAccessIterator<Item=D>
1317+
impl<I> RandomAccessIterator for Cloned<I> where
1318+
I: RandomAccessIterator,
1319+
I::Item: Deref,
1320+
<I::Item as Deref>::Target: Clone
13211321
{
13221322
#[inline]
13231323
fn indexable(&self) -> usize {
13241324
self.it.indexable()
13251325
}
13261326

13271327
#[inline]
1328-
fn idx(&mut self, index: usize) -> Option<T> {
1328+
fn idx(&mut self, index: usize) -> Option<<Self as Iterator>::Item> {
13291329
self.it.idx(index).cloned()
13301330
}
13311331
}
@@ -1400,11 +1400,14 @@ pub struct Chain<A, B> {
14001400
}
14011401

14021402
#[stable(feature = "rust1", since = "1.0.0")]
1403-
impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<Item=T> {
1404-
type Item = T;
1403+
impl<A, B> Iterator for Chain<A, B> where
1404+
A: Iterator,
1405+
B: Iterator<Item = A::Item>
1406+
{
1407+
type Item = A::Item;
14051408

14061409
#[inline]
1407-
fn next(&mut self) -> Option<T> {
1410+
fn next(&mut self) -> Option<A::Item> {
14081411
if self.flag {
14091412
self.b.next()
14101413
} else {
@@ -1434,12 +1437,12 @@ impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<It
14341437
}
14351438

14361439
#[stable(feature = "rust1", since = "1.0.0")]
1437-
impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
1438-
A: DoubleEndedIterator<Item=T>,
1439-
B: DoubleEndedIterator<Item=T>,
1440+
impl<A, B> DoubleEndedIterator for Chain<A, B> where
1441+
A: DoubleEndedIterator,
1442+
B: DoubleEndedIterator<Item=A::Item>,
14401443
{
14411444
#[inline]
1442-
fn next_back(&mut self) -> Option<T> {
1445+
fn next_back(&mut self) -> Option<A::Item> {
14431446
match self.b.next_back() {
14441447
Some(x) => Some(x),
14451448
None => self.a.next_back()
@@ -1448,9 +1451,9 @@ impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
14481451
}
14491452

14501453
#[unstable(feature = "core", reason = "trait is experimental")]
1451-
impl<T, A, B> RandomAccessIterator for Chain<A, B> where
1452-
A: RandomAccessIterator<Item=T>,
1453-
B: RandomAccessIterator<Item=T>,
1454+
impl<A, B> RandomAccessIterator for Chain<A, B> where
1455+
A: RandomAccessIterator,
1456+
B: RandomAccessIterator<Item = A::Item>,
14541457
{
14551458
#[inline]
14561459
fn indexable(&self) -> usize {
@@ -1459,7 +1462,7 @@ impl<T, A, B> RandomAccessIterator for Chain<A, B> where
14591462
}
14601463

14611464
#[inline]
1462-
fn idx(&mut self, index: usize) -> Option<T> {
1465+
fn idx(&mut self, index: usize) -> Option<A::Item> {
14631466
let len = self.a.indexable();
14641467
if index < len {
14651468
self.a.idx(index)
@@ -1479,14 +1482,12 @@ pub struct Zip<A, B> {
14791482
}
14801483

14811484
#[stable(feature = "rust1", since = "1.0.0")]
1482-
impl<T, U, A, B> Iterator for Zip<A, B> where
1483-
A: Iterator<Item = T>,
1484-
B: Iterator<Item = U>,
1485+
impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
14851486
{
1486-
type Item = (T, U);
1487+
type Item = (A::Item, B::Item);
14871488

14881489
#[inline]
1489-
fn next(&mut self) -> Option<(T, U)> {
1490+
fn next(&mut self) -> Option<(A::Item, B::Item)> {
14901491
match self.a.next() {
14911492
None => None,
14921493
Some(x) => match self.b.next() {
@@ -1515,12 +1516,12 @@ impl<T, U, A, B> Iterator for Zip<A, B> where
15151516
}
15161517

15171518
#[stable(feature = "rust1", since = "1.0.0")]
1518-
impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
1519-
A: DoubleEndedIterator + ExactSizeIterator<Item=T>,
1520-
B: DoubleEndedIterator + ExactSizeIterator<Item=U>,
1519+
impl<A, B> DoubleEndedIterator for Zip<A, B> where
1520+
A: DoubleEndedIterator + ExactSizeIterator,
1521+
B: DoubleEndedIterator + ExactSizeIterator,
15211522
{
15221523
#[inline]
1523-
fn next_back(&mut self) -> Option<(T, U)> {
1524+
fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
15241525
let a_sz = self.a.len();
15251526
let b_sz = self.b.len();
15261527
if a_sz != b_sz {
@@ -1540,17 +1541,17 @@ impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
15401541
}
15411542

15421543
#[unstable(feature = "core", reason = "trait is experimental")]
1543-
impl<T, U, A, B> RandomAccessIterator for Zip<A, B> where
1544-
A: RandomAccessIterator<Item=T>,
1545-
B: RandomAccessIterator<Item=U>,
1544+
impl<A, B> RandomAccessIterator for Zip<A, B> where
1545+
A: RandomAccessIterator,
1546+
B: RandomAccessIterator
15461547
{
15471548
#[inline]
15481549
fn indexable(&self) -> usize {
15491550
cmp::min(self.a.indexable(), self.b.indexable())
15501551
}
15511552

15521553
#[inline]
1553-
fn idx(&mut self, index: usize) -> Option<(T, U)> {
1554+
fn idx(&mut self, index: usize) -> Option<(A::Item, B::Item)> {
15541555
match self.a.idx(index) {
15551556
None => None,
15561557
Some(x) => match self.b.idx(index) {
@@ -2071,8 +2072,9 @@ pub struct Scan<I, St, F> {
20712072
}
20722073

20732074
#[stable(feature = "rust1", since = "1.0.0")]
2074-
impl<A, B, I: Iterator<Item=A>, St, F> Iterator for Scan<I, St, F> where
2075-
F: FnMut(&mut St, A) -> Option<B>,
2075+
impl<B, I, St, F> Iterator for Scan<I, St, F> where
2076+
I: Iterator,
2077+
F: FnMut(&mut St, I::Item) -> Option<B>,
20762078
{
20772079
type Item = B;
20782080

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test to see that the element type of .cloned() can be inferred
12+
// properly. Previously this would fail to deduce the type of `sum`.
13+
14+
#![feature(core)]
15+
16+
use std::iter::AdditiveIterator;
17+
18+
fn square_sum(v: &[i64]) -> i64 {
19+
let sum = v.iter().cloned().sum();
20+
sum * sum
21+
}
22+
23+
fn main() {
24+
assert_eq!(36, square_sum(&[1,2,3]));
25+
}

0 commit comments

Comments
 (0)