|
1 | 1 | // See src/libstd/primitive_docs.rs for documentation.
|
2 | 2 |
|
3 |
| -use crate::cmp::Ordering::*; |
4 |
| -use crate::cmp::*; |
| 3 | +use crate::cmp::Ordering::{self, *}; |
| 4 | +use crate::mem::transmute; |
5 | 5 |
|
6 | 6 | // Recursive macro for implementing n-ary tuple functions and operations
|
7 | 7 | //
|
@@ -61,19 +61,19 @@ macro_rules! tuple_impls {
|
61 | 61 | }
|
62 | 62 | #[inline]
|
63 | 63 | fn lt(&self, other: &($($T,)+)) -> bool {
|
64 |
| - lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
| 64 | + lexical_ord!(lt, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
65 | 65 | }
|
66 | 66 | #[inline]
|
67 | 67 | fn le(&self, other: &($($T,)+)) -> bool {
|
68 |
| - lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
| 68 | + lexical_ord!(le, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
69 | 69 | }
|
70 | 70 | #[inline]
|
71 | 71 | fn ge(&self, other: &($($T,)+)) -> bool {
|
72 |
| - lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
| 72 | + lexical_ord!(ge, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
73 | 73 | }
|
74 | 74 | #[inline]
|
75 | 75 | fn gt(&self, other: &($($T,)+)) -> bool {
|
76 |
| - lexical_ord!(gt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
| 76 | + lexical_ord!(gt, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+) |
77 | 77 | }
|
78 | 78 | }
|
79 | 79 | }
|
@@ -123,16 +123,38 @@ macro_rules! maybe_tuple_doc {
|
123 | 123 | };
|
124 | 124 | }
|
125 | 125 |
|
126 |
| -// Constructs an expression that performs a lexical ordering using method $rel. |
| 126 | +#[inline] |
| 127 | +const fn ordering_is_some(c: Option<Ordering>, x: Ordering) -> bool { |
| 128 | + // FIXME: Just use `==` once that's const-stable on `Option`s. |
| 129 | + // This isn't using `match` because that optimizes worse due to |
| 130 | + // making a two-step check (`Some` *then* the inner value). |
| 131 | + |
| 132 | + // SAFETY: There's no public guarantee for `Option<Ordering>`, |
| 133 | + // but we're core so we know that it's definitely a byte. |
| 134 | + unsafe { |
| 135 | + let c: i8 = transmute(c); |
| 136 | + let x: i8 = transmute(Some(x)); |
| 137 | + c == x |
| 138 | + } |
| 139 | +} |
| 140 | + |
| 141 | +// Constructs an expression that performs a lexical ordering using method `$rel`. |
127 | 142 | // The values are interleaved, so the macro invocation for
|
128 |
| -// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2, |
129 |
| -// a3, b3)` (and similarly for `lexical_cmp`) |
| 143 | +// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, |
| 144 | +// a2, b2, a3, b3)` (and similarly for `lexical_cmp`) |
| 145 | +// |
| 146 | +// `$ne_rel` is only used to determine the result after checking that they're |
| 147 | +// not equal, so `lt` and `le` can both just use `Less`. |
130 | 148 | macro_rules! lexical_ord {
|
131 |
| - ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { |
132 |
| - if $a != $b { lexical_ord!($rel, $a, $b) } |
133 |
| - else { lexical_ord!($rel, $($rest_a, $rest_b),+) } |
| 149 | + ($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ |
| 150 | + let c = PartialOrd::partial_cmp(&$a, &$b); |
| 151 | + if !ordering_is_some(c, Equal) { ordering_is_some(c, $ne_rel) } |
| 152 | + else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) } |
| 153 | + }}; |
| 154 | + ($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => { |
| 155 | + // Use the specific method for the last element |
| 156 | + PartialOrd::$rel(&$a, &$b) |
134 | 157 | };
|
135 |
| - ($rel: ident, $a:expr, $b:expr) => { ($a) . $rel (& $b) }; |
136 | 158 | }
|
137 | 159 |
|
138 | 160 | macro_rules! lexical_partial_cmp {
|
|
0 commit comments