Skip to content

Commit 3a11ddb

Browse files
committed
Correct tuple Ord impl, add Total{Eq,Ord} impls and add some tests.
1 parent 7103c39 commit 3a11ddb

File tree

1 file changed

+87
-19
lines changed

1 file changed

+87
-19
lines changed

src/libcore/tuple.rs

Lines changed: 87 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,17 @@ impl<A:Copy,B:Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) {
114114

115115
// macro for implementing n-ary tuple functions and operations
116116

117-
macro_rules! tuple_impls(
117+
macro_rules! tuple_impls {
118118
($(
119119
($cloneable_trait:ident, $immutable_trait:ident) {
120120
$(($get_fn:ident, $get_ref_fn:ident) -> $T:ident {
121121
$get_pattern:pat => $ret:expr
122122
})+
123123
}
124-
)+) => (
124+
)+) => {
125125
pub mod inner {
126126
use clone::Clone;
127-
#[cfg(not(test))] use cmp::{Eq, Ord};
127+
#[cfg(not(test))] use cmp::*;
128128

129129
$(
130130
pub trait $cloneable_trait<$($T),+> {
@@ -171,11 +171,19 @@ macro_rules! tuple_impls(
171171
}
172172
}
173173

174+
#[cfg(not(test))]
175+
impl<$($T:TotalEq),+> TotalEq for ($($T),+) {
176+
#[inline(always)]
177+
fn equals(&self, other: &($($T),+)) -> bool {
178+
$(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+
179+
}
180+
}
181+
174182
#[cfg(not(test))]
175183
impl<$($T:Ord),+> Ord for ($($T),+) {
176184
#[inline(always)]
177185
fn lt(&self, other: &($($T),+)) -> bool {
178-
lexical_lt!($(*self.$get_ref_fn(), *other.$get_ref_fn()),+)
186+
lexical_lt!($(self.$get_ref_fn(), other.$get_ref_fn()),+)
179187
}
180188
#[inline(always)]
181189
fn le(&self, other: &($($T),+)) -> bool { !(*other).lt(&(*self)) }
@@ -184,22 +192,44 @@ macro_rules! tuple_impls(
184192
#[inline(always)]
185193
fn gt(&self, other: &($($T),+)) -> bool { (*other).lt(&(*self)) }
186194
}
195+
196+
#[cfg(not(test))]
197+
impl<$($T:TotalOrd),+> TotalOrd for ($($T),+) {
198+
#[inline]
199+
fn cmp(&self, other: &($($T),+)) -> Ordering {
200+
lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+)
201+
}
202+
}
187203
)+
188204
}
189-
)
190-
)
191-
192-
// Constructs an expression that performs a lexical less-than ordering.
193-
// The values are interleaved, so the macro invocation for
194-
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_lt!(a1, b1, a2, b2, a3, b3)`
195-
macro_rules! lexical_lt(
196-
($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => (
197-
if $a < $b { true } else { lexical_lt!($($rest_a, $rest_b),+) }
198-
);
199-
($a:expr, $b:expr) => ($a < $b);
200-
)
201-
202-
tuple_impls!(
205+
}
206+
}
207+
208+
// Constructs an expression that performs a lexical less-than
209+
// ordering. The values are interleaved, so the macro invocation for
210+
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_lt!(a1, b1, a2, b2,
211+
// a3, b3)` (and similarly for `lexical_cmp`)
212+
macro_rules! lexical_lt {
213+
($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
214+
if *$a < *$b { true }
215+
else if !(*$b < *$a) { lexical_lt!($($rest_a, $rest_b),+) }
216+
else { false }
217+
};
218+
($a:expr, $b:expr) => { *$a < *$b };
219+
}
220+
221+
macro_rules! lexical_cmp {
222+
($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
223+
match ($a).cmp($b) {
224+
Equal => lexical_cmp!($($rest_a, $rest_b),+),
225+
ordering => ordering
226+
}
227+
};
228+
($a:expr, $b:expr) => { ($a).cmp($b) };
229+
}
230+
231+
232+
tuple_impls! {
203233
(CloneableTuple2, ImmutableTuple2) {
204234
(n0, n0_ref) -> A { (ref a,_) => a }
205235
(n1, n1_ref) -> B { (_,ref b) => b }
@@ -309,12 +339,13 @@ tuple_impls!(
309339
(n10, n10_ref) -> K { (_,_,_,_,_,_,_,_,_,_,ref k,_) => k }
310340
(n11, n11_ref) -> L { (_,_,_,_,_,_,_,_,_,_,_,ref l) => l }
311341
}
312-
)
342+
}
313343

314344
#[cfg(test)]
315345
mod tests {
316346
use super::*;
317347
use clone::Clone;
348+
use cmp::*;
318349

319350
#[test]
320351
fn test_tuple_ref() {
@@ -368,4 +399,41 @@ mod tests {
368399
assert_eq!(t.n10_ref(), &10f32);
369400
assert_eq!(t.n11_ref(), &11f64);
370401
}
402+
403+
#[test]
404+
fn test_tuple_cmp() {
405+
let small = (1u, 2u, 3u), big = (3u, 2u, 1u);
406+
407+
// Eq
408+
assert_eq!(small, small);
409+
assert_eq!(big, big);
410+
assert!(small != big);
411+
assert!(big != small);
412+
413+
// Ord
414+
assert!(small < big);
415+
assert!(!(small < small));
416+
assert!(!(big < small));
417+
assert!(!(big < big));
418+
419+
assert!(small <= small);
420+
assert!(big <= big);
421+
422+
assert!(big > small);
423+
assert!(small >= small);
424+
assert!(big >= small);
425+
assert!(big >= big);
426+
427+
// TotalEq
428+
assert!(small.equals(&small));
429+
assert!(big.equals(&big));
430+
assert!(!small.equals(&big));
431+
assert!(!big.equals(&small));
432+
433+
// TotalOrd
434+
assert_eq!(small.cmp(&small), Equal);
435+
assert_eq!(big.cmp(&big), Equal);
436+
assert_eq!(small.cmp(&big), Less);
437+
assert_eq!(big.cmp(&small), Greater);
438+
}
371439
}

0 commit comments

Comments
 (0)