Skip to content

Commit e82215d

Browse files
committed
Review changes
1 parent e840e49 commit e82215d

File tree

9 files changed

+139
-89
lines changed

9 files changed

+139
-89
lines changed

src/libcore/iter.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2542,6 +2542,64 @@ impl<A: Int> Iterator<A> for RangeStepInclusive<A> {
25422542
}
25432543
}
25442544

2545+
2546+
/// The `Step` trait identifies objects which can be stepped over in both
2547+
/// directions. The `steps_between` function provides a way to
2548+
/// compare two Step objects (it could be provided using `step()` and `Ord`,
2549+
/// but the implementation would be so inefficient as to be useless).
2550+
#[unstable = "Trait is unstable."]
2551+
pub trait Step: Ord {
2552+
/// Change self to the next object.
2553+
fn step(&mut self);
2554+
/// Change self to the previous object.
2555+
fn step_back(&mut self);
2556+
/// The steps_between two step objects.
2557+
/// a should always be less than b, so the result should never be negative.
2558+
/// Return None if it is not possible to calculate steps_between without
2559+
/// overflow.
2560+
fn steps_between(a: &Self, b: &Self) -> Option<uint>;
2561+
}
2562+
2563+
macro_rules! step_impl {
2564+
($($t:ty)*) => ($(
2565+
#[unstable = "Trait is unstable."]
2566+
impl Step for $t {
2567+
#[inline]
2568+
fn step(&mut self) { *self += 1; }
2569+
#[inline]
2570+
fn step_back(&mut self) { *self -= 1; }
2571+
#[inline]
2572+
fn steps_between(a: &$t, b: &$t) -> Option<uint> {
2573+
debug_assert!(a < b);
2574+
Some((*a - *b) as uint)
2575+
}
2576+
}
2577+
)*)
2578+
}
2579+
2580+
macro_rules! step_impl_no_between {
2581+
($($t:ty)*) => ($(
2582+
#[unstable = "Trait is unstable."]
2583+
impl Step for $t {
2584+
#[inline]
2585+
fn step(&mut self) { *self += 1; }
2586+
#[inline]
2587+
fn step_back(&mut self) { *self -= 1; }
2588+
#[inline]
2589+
fn steps_between(_a: &$t, _b: &$t) -> Option<uint> {
2590+
None
2591+
}
2592+
}
2593+
)*)
2594+
}
2595+
2596+
step_impl!(uint u8 u16 u32 int i8 i16 i32);
2597+
#[cfg(target_word_size = "64")]
2598+
step_impl!(u64 i64);
2599+
#[cfg(target_word_size = "32")]
2600+
step_impl_no_between!(u64 i64);
2601+
2602+
25452603
/// An iterator that repeats an element endlessly
25462604
#[deriving(Clone)]
25472605
#[stable]

src/libcore/ops.rs

Lines changed: 19 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,8 @@
5252
//! something to the screen.
5353
5454
use clone::Clone;
55-
use cmp::Ord;
56-
use iter::{Iterator,DoubleEndedIterator};
55+
use iter::{Step, Iterator,DoubleEndedIterator,ExactSizeIterator};
5756
use kinds::Sized;
58-
use kinds::Copy;
5957
use option::Option::{mod, Some, None};
6058

6159
/// The `Drop` trait is used to run some code when a value goes out of scope. This
@@ -839,53 +837,13 @@ pub trait SliceMut<Sized? Idx, Sized? Result> for Sized? {
839837
}
840838

841839

842-
843-
/// REVIEW could be in a better module
844-
/// The `Countable` trait identifies objects which are countable, i.e., are
845-
/// analogous to the natural numbers. A countable object can be incremented and
846-
/// and decremented and ordered. The `difference` function provides a way to
847-
/// compare two Countable objects (it could be provided using increment and Ord,
848-
/// but the implementation would be so inefficient as to be useless).
849-
#[unstable = "Trait is unstable."]
850-
pub trait Countable: Ord {
851-
// FIXME(#19391) needs a snapshot
852-
//type T;
853-
854-
/// Change self to the next object.
855-
fn increment(&mut self);
856-
/// Change self to the previous object.
857-
fn decrement(&mut self);
858-
/// The difference between two countable objects.
859-
/// Temporarily a uint, should be an associated type, but
860-
// FIXME(#19391) needs a snapshot
861-
fn difference(a: &Self, b: &Self) -> uint;
862-
//fn difference(a: &Self, b: &Self) -> <Self as Countable>::T;
863-
}
864-
865-
macro_rules! countable_impl(
866-
($($t:ty)*) => ($(
867-
#[unstable = "Trait is unstable."]
868-
impl Countable for $t {
869-
// FIXME(#19391) needs a snapshot
870-
//type T = uint;
871-
872-
#[inline]
873-
fn increment(&mut self) { *self += 1; }
874-
#[inline]
875-
fn decrement(&mut self) { *self -= 1; }
876-
#[inline]
877-
fn difference(a: &$t, b: &$t) -> uint { (*a - *b) as uint }
878-
}
879-
)*)
880-
)
881-
882-
countable_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
883-
884840
/// An unbounded range.
841+
#[deriving(Copy)]
885842
#[lang="full_range"]
886843
pub struct FullRange;
887844

888-
/// A range which i bounded at both ends.
845+
/// A (half-open) range which is bounded at both ends.
846+
#[deriving(Copy)]
889847
#[lang="range"]
890848
pub struct Range<Idx> {
891849
/// The lower bound of the range (inclusive).
@@ -895,13 +853,13 @@ pub struct Range<Idx> {
895853
}
896854

897855
// FIXME(#19391) needs a snapshot
898-
//impl<Idx: Clone + Countable<T=uint>> Iterator<Idx> for Range<Idx> {
899-
impl<Idx: Clone + Countable> Iterator<Idx> for Range<Idx> {
856+
//impl<Idx: Clone + Step<T=uint>> Iterator<Idx> for Range<Idx> {
857+
impl<Idx: Clone + Step> Iterator<Idx> for Range<Idx> {
900858
#[inline]
901859
fn next(&mut self) -> Option<Idx> {
902860
if self.start < self.end {
903861
let result = self.start.clone();
904-
self.start.increment();
862+
self.start.step();
905863
return Some(result);
906864
}
907865

@@ -910,44 +868,46 @@ impl<Idx: Clone + Countable> Iterator<Idx> for Range<Idx> {
910868

911869
#[inline]
912870
fn size_hint(&self) -> (uint, Option<uint>) {
913-
let hint = Countable::difference(&self.end, &self.start);
914-
(hint, Some(hint))
871+
if let Some(hint) = Step::steps_between(&self.end, &self.start) {
872+
(hint, Some(hint))
873+
} else {
874+
(0, None)
875+
}
915876
}
916877
}
917878

918-
impl<Idx: Clone + Countable> DoubleEndedIterator<Idx> for Range<Idx> {
879+
impl<Idx: Clone + Step> DoubleEndedIterator<Idx> for Range<Idx> {
919880
#[inline]
920881
fn next_back(&mut self) -> Option<Idx> {
921882
if self.start < self.end {
922-
self.end.decrement();
883+
self.end.step_back();
923884
return Some(self.end.clone());
924885
}
925886

926887
return None;
927888
}
928889
}
929890

891+
impl<Idx: Clone + Step> ExactSizeIterator<Idx> for Range<Idx> {}
892+
930893
/// A range which is only bounded below.
894+
#[deriving(Copy)]
931895
#[lang="range_from"]
932896
pub struct RangeFrom<Idx> {
933897
/// The lower bound of the range (inclusive).
934898
pub start: Idx,
935899
}
936900

937-
impl<Idx: Clone + Countable> Iterator<Idx> for RangeFrom<Idx> {
901+
impl<Idx: Clone + Step> Iterator<Idx> for RangeFrom<Idx> {
938902
#[inline]
939903
fn next(&mut self) -> Option<Idx> {
940904
// Deliberately overflow so we loop forever.
941905
let result = self.start.clone();
942-
self.start.increment();
906+
self.start.step();
943907
return Some(result);
944908
}
945909
}
946910

947-
impl<Idx: Copy> Copy for Range<Idx> {}
948-
impl<Idx: Copy> Copy for RangeFrom<Idx> {}
949-
impl Copy for FullRange {}
950-
951911

952912
/// The `Deref` trait is used to specify the functionality of dereferencing
953913
/// operations like `*v`.

src/libcoretest/ops.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,25 @@ fn alloc_obj_with_dtor(b: &mut Bencher) {
3434
#[test]
3535
fn test_range() {
3636
let r = Range { start: 2u, end: 10 };
37+
let mut count = 0u;
3738
for (i, ri) in r.enumerate() {
3839
assert!(ri == i + 2);
3940
assert!(ri >= 2u && ri < 10u);
41+
count += 1;
4042
}
43+
assert!(count == 8);
4144
}
4245

4346
#[test]
4447
fn test_range_from() {
4548
let r = RangeFrom { start: 2u };
49+
let mut count = 0u;
4650
for (i, ri) in r.take(10).enumerate() {
4751
assert!(ri == i + 2);
4852
assert!(ri >= 2u && ri < 12u);
53+
count += 1;
4954
}
55+
assert!(count == 10);
5056
}
5157

5258
#[test]

src/librustc/middle/infer/error_reporting.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
366366
infer::MatchExpressionArm(_, _) => "match arms have incompatible types",
367367
infer::IfExpression(_) => "if and else have incompatible types",
368368
infer::IfExpressionWithNoElse(_) => "if may be missing an else clause",
369+
infer::RangeExpression(_) => "start and end of range have incompatible types",
369370
infer::EquatePredicate(_) => "equality predicate not satisfied",
370371
};
371372

@@ -1490,6 +1491,9 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
14901491
infer::IfExpressionWithNoElse(_) => {
14911492
format!("if may be missing an else clause")
14921493
}
1494+
infer::RangeExpression(_) => {
1495+
format!("start and end of range have compatible types")
1496+
}
14931497
infer::EquatePredicate(_) => {
14941498
format!("equality where clause is satisfied")
14951499
}

src/librustc/middle/infer/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ pub enum TypeOrigin {
127127
// Computing common supertype of an if expression with no else counter-part
128128
IfExpressionWithNoElse(Span),
129129

130+
// Computing common supertype in a range expression
131+
RangeExpression(Span),
132+
130133
// `where a == b`
131134
EquatePredicate(Span),
132135
}
@@ -1084,6 +1087,7 @@ impl TypeOrigin {
10841087
MatchExpressionArm(match_span, _) => match_span,
10851088
IfExpression(span) => span,
10861089
IfExpressionWithNoElse(span) => span,
1090+
RangeExpression(span) => span,
10871091
EquatePredicate(span) => span,
10881092
}
10891093
}
@@ -1117,6 +1121,9 @@ impl<'tcx> Repr<'tcx> for TypeOrigin {
11171121
IfExpressionWithNoElse(a) => {
11181122
format!("IfExpressionWithNoElse({})", a.repr(tcx))
11191123
}
1124+
RangeExpression(a) => {
1125+
format!("RangeExpression({})", a.repr(tcx))
1126+
}
11201127
EquatePredicate(a) => {
11211128
format!("EquatePredicate({})", a.repr(tcx))
11221129
}

src/librustc_typeck/check/mod.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4279,44 +4279,59 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
42794279
}
42804280
}
42814281
ast::ExprRange(ref start, ref end) => {
4282-
let mut some_err = false;
4283-
42844282
check_expr(fcx, &**start);
42854283
let t_start = fcx.expr_ty(&**start);
4286-
if ty::type_is_error(t_start) {
4287-
fcx.write_ty(start.id, t_start);
4288-
some_err = true;
4289-
}
42904284

4291-
if let &Some(ref e) = end {
4292-
check_expr_has_type(fcx, &**e, t_start);
4293-
let t_end = fcx.expr_ty(&**e);
4294-
if ty::type_is_error(t_end) {
4295-
fcx.write_ty(e.id, t_end);
4296-
some_err = true;
4297-
}
4298-
}
4285+
let idx_type = if let &Some(ref e) = end {
4286+
check_expr(fcx, &**e);
4287+
let t_end = fcx.expr_ty(&**e);
4288+
if ty::type_is_error(t_end) {
4289+
ty::mk_err()
4290+
} else if t_start == ty::mk_err() {
4291+
ty::mk_err()
4292+
} else {
4293+
infer::common_supertype(fcx.infcx(),
4294+
infer::RangeExpression(expr.span),
4295+
true,
4296+
t_start,
4297+
t_end)
4298+
}
4299+
} else {
4300+
t_start
4301+
};
42994302

4300-
// Note that we don't check the type of the start/end satisfy any
4303+
// Note that we don't check the type of start/end satisfy any
43014304
// bounds because right the range structs do not have any. If we add
43024305
// some bounds, then we'll need to check `t_start` against them here.
43034306

4304-
if !some_err {
4307+
let range_type = if idx_type == ty::mk_err() {
4308+
ty::mk_err()
4309+
} else {
43054310
// Find the did from the appropriate lang item.
43064311
let did = if end.is_some() {
43074312
// Range
4308-
fcx.tcx().lang_items.range_struct()
4313+
tcx.lang_items.range_struct()
43094314
} else {
43104315
// RangeFrom
4311-
fcx.tcx().lang_items.range_from_struct()
4316+
tcx.lang_items.range_from_struct()
43124317
};
4318+
43134319
if let Some(did) = did {
4314-
let substs = Substs::new_type(vec![t_start], vec![]);
4315-
fcx.write_ty(id, ty::mk_struct(tcx, did, substs));
4320+
let polytype = ty::lookup_item_type(tcx, did);
4321+
let substs = Substs::new_type(vec![idx_type], vec![]);
4322+
let bounds = polytype.generics.to_bounds(tcx, &substs);
4323+
fcx.add_obligations_for_parameters(
4324+
traits::ObligationCause::new(expr.span,
4325+
fcx.body_id,
4326+
traits::ItemObligation(did)),
4327+
&bounds);
4328+
4329+
ty::mk_struct(tcx, did, substs)
43164330
} else {
4317-
fcx.write_ty(id, ty::mk_err());
4331+
ty::mk_err()
43184332
}
4319-
}
4333+
};
4334+
fcx.write_ty(id, range_type);
43204335
}
43214336

43224337
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
pub fn main() {
1414
// Mixed types.
1515
let _ = 0u..10i;
16-
//~^ ERROR mismatched types: expected `uint`, found `int`
16+
//~^ ERROR start and end of range have incompatible types
1717

1818
// Float => does not implement iterator.
1919
for i in 0f32..42f32 {}

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,6 @@
1111
// Test range syntax - borrow errors.
1212

1313
pub fn main() {
14-
let x = &42i;
15-
{
16-
let y = 42i;
17-
let r = x..&y;
18-
//~^ ERROR `y` does not live long enough
19-
}
20-
2114
let r = {
2215
(&42i)..&42
2316
//~^ ERROR borrowed value does not live long enough

src/test/run-pass/range.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,11 @@ pub fn main() {
3838

3939
let _ = 0u..4+4-3;
4040
let _ = 0..foo();
41+
42+
// Test we can use two different types with a common supertype.
43+
let x = &42i;
44+
{
45+
let y = 42i;
46+
let _ = x..&y;
47+
}
4148
}

0 commit comments

Comments
 (0)