Skip to content

Commit c2bda2a

Browse files
committed
Auto merge of #21806 - edwardw:new-range-impl, r=alexcrichton
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 #21595 Closes #21649 Closes #21672
2 parents 76ce1ea + b9c055c commit c2bda2a

File tree

3 files changed

+76
-73
lines changed

3 files changed

+76
-73
lines changed

src/libcore/iter.rs

+47-69
Original file line numberDiff line numberDiff line change
@@ -2797,93 +2797,71 @@ impl<A: Int> Iterator for RangeStepInclusive<A> {
27972797
}
27982798
}
27992799

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

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

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

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

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

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

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

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

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

src/test/compile-fail/range-1.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ pub fn main() {
1717

1818
// Float => does not implement iterator.
1919
for i in 0f32..42f32 {}
20-
//~^ ERROR `core::iter::Iterator` is not implemented for the type `core::ops::Range<f32>`
21-
//~^^ ERROR
22-
//~^^^ ERROR
23-
// FIXME(#21528) not fulfilled obligation error should be reported once, not thrice
20+
//~^ ERROR the trait `core::num::Int` is not implemented for the type `f32`
2421

2522
// Unsized type.
2623
let arr: &[_] = &[1u32, 2, 3];

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

+28
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)