Skip to content

Commit cd977ee

Browse files
committed
Make sure type inference with a..b as good as range(a,b)
The new `::ops::Range` has separated implementations for each of the numeric types, while the old `::iter::Range` has one for type `Int`. However, we do not take output bindings into account when selecting traits. So it confuses `typeck` and makes the new range does not work as good as the old one when it comes to type inference. This patch implements `Iterator` for the new range for one type `Int`. This limitation could be lifted, however, if we ever reconsider the output types' role in type inference. Closes rust-lang#21595 Closes rust-lang#21649 Closes rust-lang#21672
1 parent 474b324 commit cd977ee

File tree

2 files changed

+75
-69
lines changed

2 files changed

+75
-69
lines changed

src/libcore/iter.rs

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,93 +2796,71 @@ impl<A: Int> Iterator for RangeStepInclusive<A> {
27962796
}
27972797
}
27982798

2799-
macro_rules! range_impl {
2799+
macro_rules! range_exact_iter_impl {
28002800
($($t:ty)*) => ($(
28012801
#[stable(feature = "rust1", since = "1.0.0")]
2802-
impl Iterator for ::ops::Range<$t> {
2803-
type Item = $t;
2804-
2802+
impl ExactSizeIterator for ::ops::Range<$t> {
28052803
#[inline]
2806-
fn next(&mut self) -> Option<$t> {
2807-
if self.start < self.end {
2808-
let result = self.start;
2809-
self.start += 1;
2810-
return Some(result);
2811-
}
2812-
2813-
return None;
2814-
}
2815-
2816-
#[inline]
2817-
fn size_hint(&self) -> (usize, Option<usize>) {
2804+
fn len(&self) -> usize {
28182805
debug_assert!(self.end >= self.start);
2819-
let hint = (self.end - self.start) as usize;
2820-
(hint, Some(hint))
2806+
(self.end - self.start) as usize
28212807
}
28222808
}
2823-
2824-
#[stable(feature = "rust1", since = "1.0.0")]
2825-
impl ExactSizeIterator for ::ops::Range<$t> {}
28262809
)*)
28272810
}
28282811

2829-
macro_rules! range_impl_no_hint {
2830-
($($t:ty)*) => ($(
2831-
#[stable(feature = "rust1", since = "1.0.0")]
2832-
impl Iterator for ::ops::Range<$t> {
2833-
type Item = $t;
2834-
2835-
#[inline]
2836-
fn next(&mut self) -> Option<$t> {
2837-
if self.start < self.end {
2838-
let result = self.start;
2839-
self.start += 1;
2840-
return Some(result);
2841-
}
2812+
#[stable(feature = "rust1", since = "1.0.0")]
2813+
impl<A: Int> Iterator for ::ops::Range<A> {
2814+
type Item = A;
28422815

2843-
return None;
2844-
}
2816+
#[inline]
2817+
fn next(&mut self) -> Option<A> {
2818+
if self.start < self.end {
2819+
let result = self.start;
2820+
self.start = self.start + Int::one();
2821+
Some(result)
2822+
} else {
2823+
None
28452824
}
2846-
)*)
2847-
}
2848-
2849-
macro_rules! range_other_impls {
2850-
($($t:ty)*) => ($(
2851-
#[stable(feature = "rust1", since = "1.0.0")]
2852-
impl DoubleEndedIterator for ::ops::Range<$t> {
2853-
#[inline]
2854-
fn next_back(&mut self) -> Option<$t> {
2855-
if self.start < self.end {
2856-
self.end -= 1;
2857-
return Some(self.end);
2858-
}
2825+
}
28592826

2860-
return None;
2861-
}
2862-
}
2827+
#[inline]
2828+
fn size_hint(&self) -> (usize, Option<usize>) {
2829+
debug_assert!(self.end >= self.start);
2830+
let hint = (self.end - self.start).to_uint();
2831+
(hint.unwrap_or(0), hint)
2832+
}
2833+
}
28632834

2864-
#[stable(feature = "rust1", since = "1.0.0")]
2865-
impl Iterator for ::ops::RangeFrom<$t> {
2866-
type Item = $t;
2835+
range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
2836+
#[cfg(target_pointer_width = "64")]
2837+
range_exact_iter_impl!(u64 i64);
28672838

2868-
#[inline]
2869-
fn next(&mut self) -> Option<$t> {
2870-
let result = self.start;
2871-
self.start += 1;
2872-
debug_assert!(result < self.start);
2873-
return Some(result);
2874-
}
2839+
#[stable(feature = "rust1", since = "1.0.0")]
2840+
impl<A: Int> DoubleEndedIterator for ::ops::Range<A> {
2841+
#[inline]
2842+
fn next_back(&mut self) -> Option<A> {
2843+
if self.start < self.end {
2844+
self.end = self.end - Int::one();
2845+
Some(self.end)
2846+
} else {
2847+
None
28752848
}
2876-
)*)
2849+
}
28772850
}
28782851

2879-
range_impl!(usize u8 u16 u32 isize i8 i16 i32);
2880-
#[cfg(target_pointer_width = "64")]
2881-
range_impl!(u64 i64);
2882-
#[cfg(target_pointer_width = "32")]
2883-
range_impl_no_hint!(u64 i64);
2852+
#[stable(feature = "rust1", since = "1.0.0")]
2853+
impl<A: Int> Iterator for ::ops::RangeFrom<A> {
2854+
type Item = A;
28842855

2885-
range_other_impls!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
2856+
#[inline]
2857+
fn next(&mut self) -> Option<A> {
2858+
let result = self.start;
2859+
self.start = self.start + Int::one();
2860+
debug_assert!(result < self.start);
2861+
Some(result)
2862+
}
2863+
}
28862864

28872865
/// An iterator that repeats an element endlessly
28882866
#[derive(Clone)]

src/test/run-pass/range-type-infer.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
// Make sure the type inference for the new range expression work as
12+
// good as the old one. Check out issue #21672, #21595 and #21649 for
13+
// more details.
14+
15+
fn main() {
16+
let xs = (0..8).map(|i| i == 1u64).collect::<Vec<_>>();
17+
assert_eq!(xs[1], true);
18+
let xs = (0..8).map(|i| 1u64 == i).collect::<Vec<_>>();
19+
assert_eq!(xs[1], true);
20+
let xs: Vec<u8> = (0..10).collect();
21+
assert_eq!(xs.len(), 10);
22+
23+
for x in 0..10 { x % 2; }
24+
for x in 0..100 { x as f32; }
25+
26+
let array = [true, false];
27+
for i in 0..1 { array[i]; }
28+
}

0 commit comments

Comments
 (0)