1 use crate::deriving
::generic
::ty
::*;
2 use crate::deriving
::generic
::*;
3 use crate::deriving
::path_std
;
4 use rustc_ast
::MetaItem
;
5 use rustc_expand
::base
::{Annotatable, ExtCtxt}
;
6 use rustc_span
::symbol
::{sym, Ident}
;
8 use thin_vec
::thin_vec
;
10 pub fn expand_deriving_ord(
15 push
: &mut dyn FnMut(Annotatable
),
18 let attrs
= thin_vec
![cx
.attr_word(sym
::inline
, span
)];
19 let trait_def
= TraitDef
{
21 path
: path_std
!(cmp
::Ord
),
22 skip_path_as_bound
: false,
23 additional_bounds
: Vec
::new(),
24 supports_unions
: false,
25 methods
: vec
![MethodDef
{
27 generics
: Bounds
::empty(),
29 nonself_args
: vec
![(self_ref(), sym
::other
)],
30 ret_ty
: Path(path_std
!(cmp
::Ordering
)),
32 fieldless_variants_strategy
: FieldlessVariantsStrategy
::Unify
,
33 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| cs_cmp(a
, b
, c
))),
35 associated_types
: Vec
::new(),
39 trait_def
.expand(cx
, mitem
, item
, push
)
42 pub fn cs_cmp(cx
: &mut ExtCtxt
<'_
>, span
: Span
, substr
: &Substructure
<'_
>) -> BlockOrExpr
{
43 let test_id
= Ident
::new(sym
::cmp
, span
);
44 let equal_path
= cx
.path_global(span
, cx
.std_path(&[sym
::cmp
, sym
::Ordering
, sym
::Equal
]));
45 let cmp_path
= cx
.std_path(&[sym
::cmp
, sym
::Ord
, sym
::cmp
]);
49 // match ::core::cmp::Ord::cmp(&self.x, &other.x) {
50 // ::std::cmp::Ordering::Equal =>
51 // ::core::cmp::Ord::cmp(&self.y, &other.y),
55 // foldr nests the if-elses correctly, leaving the first field
56 // as the outermost one, and the last as the innermost.
61 |cx
, fold
| match fold
{
62 CsFold
::Single(field
) => {
63 let [other_expr
] = &field
.other_selflike_exprs
[..] else {
64 cx
.span_bug(field
.span
, "not exactly 2 arguments in `derive(Ord)`");
66 let args
= vec
![field
.self_expr
.clone(), other_expr
.clone()];
67 cx
.expr_call_global(field
.span
, cmp_path
.clone(), args
)
69 CsFold
::Combine(span
, expr1
, expr2
) => {
70 let eq_arm
= cx
.arm(span
, cx
.pat_path(span
, equal_path
.clone()), expr1
);
72 cx
.arm(span
, cx
.pat_ident(span
, test_id
), cx
.expr_ident(span
, test_id
));
73 cx
.expr_match(span
, expr2
, vec
![eq_arm
, neq_arm
])
75 CsFold
::Fieldless
=> cx
.expr_path(equal_path
.clone()),
78 BlockOrExpr
::new_expr(expr
)