Avoid the unnecessary innermost match in partial_cmp
/cmp
.
We currently do a match on the comparison of every field in a struct or enum variant. But the last field has a degenerate match like this: ``` match ::core::cmp::Ord::cmp(&self.y, &other.y) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, ``` This commit changes it to this: ``` ::core::cmp::Ord::cmp(&self.y, &other.y), ``` This is fairly straightforward thanks to the existing `cs_fold1` function. The commit also removes the `cs_fold` function which is no longer used. (Note: there is some repetition now in `cs_cmp` and `cs_partial_cmp`. I will remove that in a follow-up PR.)
This commit is contained in:
parent
2c911dc16f
commit
0ee79f2c5a
4 changed files with 57 additions and 139 deletions
|
@ -70,7 +70,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
|
|||
// cmp => cmp
|
||||
// }
|
||||
//
|
||||
let expr = cs_fold(
|
||||
let expr = cs_fold1(
|
||||
// foldr nests the if-elses correctly, leaving the first field
|
||||
// as the outermost one, and the last as the innermost.
|
||||
false,
|
||||
|
@ -79,15 +79,12 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
|
|||
// ::std::cmp::Ordering::Equal => old,
|
||||
// cmp => cmp
|
||||
// }
|
||||
|
||||
let new = {
|
||||
let [other_f] = other_fs else {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
|
||||
};
|
||||
|
||||
let args =
|
||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
||||
|
||||
cx.expr_call_global(span, cmp_path.clone(), args)
|
||||
};
|
||||
|
||||
|
@ -96,7 +93,21 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
|
|||
|
||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
||||
},
|
||||
cx.expr_path(equals_path.clone()),
|
||||
|cx, args| match args {
|
||||
Some((span, self_f, other_fs)) => {
|
||||
let new = {
|
||||
let [other_f] = other_fs else {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
|
||||
};
|
||||
let args =
|
||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
||||
cx.expr_call_global(span, cmp_path.clone(), args)
|
||||
};
|
||||
|
||||
new
|
||||
}
|
||||
None => cx.expr_path(equals_path.clone()),
|
||||
},
|
||||
Box::new(|cx, span, tag_tuple| {
|
||||
if tag_tuple.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
|
||||
|
|
|
@ -2,7 +2,8 @@ use crate::deriving::generic::ty::*;
|
|||
use crate::deriving::generic::*;
|
||||
use crate::deriving::{path_std, pathvec_std};
|
||||
|
||||
use rustc_ast::MetaItem;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{Expr, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
|
@ -51,7 +52,6 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
|
|||
let test_id = Ident::new(sym::cmp, span);
|
||||
let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
||||
let ordering_expr = cx.expr_path(ordering.clone());
|
||||
let equals_expr = cx.expr_some(span, ordering_expr);
|
||||
|
||||
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
|
||||
|
||||
|
@ -68,7 +68,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
|
|||
// cmp => cmp
|
||||
// }
|
||||
//
|
||||
let expr = cs_fold(
|
||||
let expr = cs_fold1(
|
||||
// foldr nests the if-elses correctly, leaving the first field
|
||||
// as the outermost one, and the last as the innermost.
|
||||
false,
|
||||
|
@ -94,7 +94,21 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
|
|||
|
||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
||||
},
|
||||
equals_expr,
|
||||
|cx: &mut ExtCtxt<'_>, args: Option<(Span, P<Expr>, &[P<Expr>])>| match args {
|
||||
Some((span, self_f, other_fs)) => {
|
||||
let new = {
|
||||
let [other_f] = other_fs else {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
|
||||
};
|
||||
let args =
|
||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
||||
cx.expr_call_global(span, partial_cmp_path.clone(), args)
|
||||
};
|
||||
|
||||
new
|
||||
}
|
||||
None => cx.expr_some(span, ordering_expr.clone()),
|
||||
},
|
||||
Box::new(|cx, span, tag_tuple| {
|
||||
if tag_tuple.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
|
||||
|
|
|
@ -1694,31 +1694,6 @@ fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P<Expr> {
|
|||
cx.span_bug(trait_span, "static function in `derive`")
|
||||
}
|
||||
|
||||
/// Fold the fields. `use_foldl` controls whether this is done
|
||||
/// left-to-right (`true`) or right-to-left (`false`).
|
||||
pub fn cs_fold<F>(
|
||||
use_foldl: bool,
|
||||
f: F,
|
||||
base: P<Expr>,
|
||||
enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substructure: &Substructure<'_>,
|
||||
) -> P<Expr>
|
||||
where
|
||||
F: FnMut(&mut ExtCtxt<'_>, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
|
||||
{
|
||||
match *substructure.fields {
|
||||
EnumMatching(.., ref all_fields) | Struct(_, ref all_fields) => {
|
||||
cs_fold_fields(use_foldl, f, base, cx, all_fields)
|
||||
}
|
||||
EnumNonMatchingCollapsed(..) => {
|
||||
cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure)
|
||||
}
|
||||
StaticEnum(..) | StaticStruct(..) => cs_fold_static(cx, trait_span),
|
||||
}
|
||||
}
|
||||
|
||||
/// Function to fold over fields, with three cases, to generate more efficient and concise code.
|
||||
/// When the `substructure` has grouped fields, there are two cases:
|
||||
/// Zero fields: call the base case function with `None` (like the usual base case of `cs_fold`).
|
||||
|
|
|
@ -161,13 +161,7 @@ impl ::core::cmp::PartialOrd for Point {
|
|||
-> ::core::option::Option<::core::cmp::Ordering> {
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y)
|
||||
{
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y),
|
||||
cmp => cmp,
|
||||
}
|
||||
}
|
||||
|
@ -179,11 +173,7 @@ impl ::core::cmp::Ord for Point {
|
|||
fn cmp(&self, other: &Point) -> ::core::cmp::Ordering {
|
||||
match ::core::cmp::Ord::cmp(&self.x, &other.x) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
match ::core::cmp::Ord::cmp(&self.y, &other.y) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&self.y, &other.y),
|
||||
cmp => cmp,
|
||||
}
|
||||
}
|
||||
|
@ -323,13 +313,7 @@ impl ::core::cmp::PartialOrd for Big {
|
|||
&other.b7) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&self.b8,
|
||||
&other.b8) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&self.b8, &other.b8),
|
||||
cmp => cmp,
|
||||
},
|
||||
cmp => cmp,
|
||||
|
@ -365,11 +349,7 @@ impl ::core::cmp::Ord for Big {
|
|||
::core::cmp::Ordering::Equal =>
|
||||
match ::core::cmp::Ord::cmp(&self.b7, &other.b7) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
match ::core::cmp::Ord::cmp(&self.b8, &other.b8) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&self.b8, &other.b8),
|
||||
cmp => cmp,
|
||||
},
|
||||
cmp => cmp,
|
||||
|
@ -461,11 +441,7 @@ impl ::core::cmp::PartialOrd for Packed {
|
|||
-> ::core::option::Option<::core::cmp::Ordering> {
|
||||
let Self(__self_0_0) = *self;
|
||||
let Self(__self_1_0) = *other;
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&__self_0_0, &__self_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
}
|
||||
::core::cmp::PartialOrd::partial_cmp(&__self_0_0, &__self_1_0)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
|
@ -475,10 +451,7 @@ impl ::core::cmp::Ord for Packed {
|
|||
fn cmp(&self, other: &Packed) -> ::core::cmp::Ordering {
|
||||
let Self(__self_0_0) = *self;
|
||||
let Self(__self_1_0) = *other;
|
||||
match ::core::cmp::Ord::cmp(&__self_0_0, &__self_1_0) {
|
||||
::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
}
|
||||
::core::cmp::Ord::cmp(&__self_0_0, &__self_1_0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -621,13 +594,7 @@ impl ::core::cmp::PartialOrd for Enum1 {
|
|||
match (&*self, &*other) {
|
||||
(&Enum1::Single { x: ref __self_0 }, &Enum1::Single {
|
||||
x: ref __arg_1_0 }) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&*__self_0, &*__arg_1_0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -639,11 +606,7 @@ impl ::core::cmp::Ord for Enum1 {
|
|||
match (&*self, &*other) {
|
||||
(&Enum1::Single { x: ref __self_0 }, &Enum1::Single {
|
||||
x: ref __arg_1_0 }) =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -873,26 +836,16 @@ impl ::core::cmp::PartialOrd for Mixed {
|
|||
if __self_vi == __arg_1_vi {
|
||||
match (&*self, &*other) {
|
||||
(&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0),
|
||||
(&Mixed::S { d1: ref __self_0, d2: ref __self_1 },
|
||||
&Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_1,
|
||||
&*__arg_1_1) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&*__self_1,
|
||||
&*__arg_1_1),
|
||||
cmp => cmp,
|
||||
},
|
||||
_ =>
|
||||
|
@ -913,20 +866,12 @@ impl ::core::cmp::Ord for Mixed {
|
|||
if __self_vi == __arg_1_vi {
|
||||
match (&*self, &*other) {
|
||||
(&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0),
|
||||
(&Mixed::S { d1: ref __self_0, d2: ref __self_1 },
|
||||
&Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_1, &*__arg_1_1) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&*__self_1, &*__arg_1_1),
|
||||
cmp => cmp,
|
||||
},
|
||||
_ => ::core::cmp::Ordering::Equal,
|
||||
|
@ -1054,29 +999,14 @@ impl ::core::cmp::PartialOrd for Fielded {
|
|||
if __self_vi == __arg_1_vi {
|
||||
match (&*self, &*other) {
|
||||
(&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0),
|
||||
(&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0),
|
||||
(&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) =>
|
||||
match ::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0) {
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal)
|
||||
=>
|
||||
::core::option::Option::Some(::core::cmp::Ordering::Equal),
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::PartialOrd::partial_cmp(&*__self_0,
|
||||
&*__arg_1_0),
|
||||
_ => unsafe { ::core::intrinsics::unreachable() }
|
||||
}
|
||||
} else {
|
||||
|
@ -1094,23 +1024,11 @@ impl ::core::cmp::Ord for Fielded {
|
|||
if __self_vi == __arg_1_vi {
|
||||
match (&*self, &*other) {
|
||||
(&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0),
|
||||
(&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0),
|
||||
(&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) =>
|
||||
match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) {
|
||||
::core::cmp::Ordering::Equal =>
|
||||
::core::cmp::Ordering::Equal,
|
||||
cmp => cmp,
|
||||
},
|
||||
::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0),
|
||||
_ => unsafe { ::core::intrinsics::unreachable() }
|
||||
}
|
||||
} else { ::core::cmp::Ord::cmp(&__self_vi, &__arg_1_vi) }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue