1 use crate::deriving
::generic
::ty
::*;
2 use crate::deriving
::generic
::*;
3 use crate::deriving
::path_std
;
6 use rustc_ast
::{self as ast, Expr, MetaItem}
;
7 use rustc_expand
::base
::{Annotatable, ExtCtxt}
;
8 use rustc_span
::symbol
::{sym, Ident}
;
11 pub fn expand_deriving_ord(
16 push
: &mut dyn FnMut(Annotatable
),
18 let inline
= cx
.meta_word(span
, sym
::inline
);
19 let attrs
= vec
![cx
.attribute(inline
)];
20 let trait_def
= TraitDef
{
22 attributes
: Vec
::new(),
23 path
: path_std
!(cmp
::Ord
),
24 additional_bounds
: Vec
::new(),
25 generics
: Bounds
::empty(),
27 supports_unions
: false,
28 methods
: vec
![MethodDef
{
30 generics
: Bounds
::empty(),
31 explicit_self
: borrowed_explicit_self(),
32 args
: vec
![(borrowed_self(), sym
::other
)],
33 ret_ty
: Literal(path_std
!(cmp
::Ordering
)),
36 unify_fieldless_variants
: true,
37 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| cs_cmp(a
, b
, c
))),
39 associated_types
: Vec
::new(),
42 trait_def
.expand(cx
, mitem
, item
, push
)
45 pub fn ordering_collapsed(
48 self_arg_tags
: &[Ident
],
50 let lft
= cx
.expr_addr_of(span
, cx
.expr_ident(span
, self_arg_tags
[0]));
51 let rgt
= cx
.expr_addr_of(span
, cx
.expr_ident(span
, self_arg_tags
[1]));
52 let fn_cmp_path
= cx
.std_path(&[sym
::cmp
, sym
::Ord
, sym
::cmp
]);
53 cx
.expr_call_global(span
, fn_cmp_path
, vec
![lft
, rgt
])
56 pub fn cs_cmp(cx
: &mut ExtCtxt
<'_
>, span
: Span
, substr
: &Substructure
<'_
>) -> P
<Expr
> {
57 let test_id
= Ident
::new(sym
::cmp
, span
);
58 let equals_path
= cx
.path_global(span
, cx
.std_path(&[sym
::cmp
, sym
::Ordering
, sym
::Equal
]));
60 let cmp_path
= cx
.std_path(&[sym
::cmp
, sym
::Ord
, sym
::cmp
]);
64 // match ::std::cmp::Ord::cmp(&self_field1, &other_field1) {
65 // ::std::cmp::Ordering::Equal =>
66 // match ::std::cmp::Ord::cmp(&self_field2, &other_field2) {
67 // ::std::cmp::Ordering::Equal => {
76 // foldr nests the if-elses correctly, leaving the first field
77 // as the outermost one, and the last as the innermost.
79 |cx
, span
, old
, self_f
, other_fs
| {
81 // ::std::cmp::Ordering::Equal => old,
86 let other_f
= match other_fs
{
88 _
=> cx
.span_bug(span
, "not exactly 2 arguments in `derive(Ord)`"),
92 vec
![cx
.expr_addr_of(span
, self_f
), cx
.expr_addr_of(span
, other_f
.clone())];
94 cx
.expr_call_global(span
, cmp_path
.clone(), args
)
97 let eq_arm
= cx
.arm(span
, cx
.pat_path(span
, equals_path
.clone()), old
);
98 let neq_arm
= cx
.arm(span
, cx
.pat_ident(span
, test_id
), cx
.expr_ident(span
, test_id
));
100 cx
.expr_match(span
, new
, vec
![eq_arm
, neq_arm
])
102 cx
.expr_path(equals_path
.clone()),
103 Box
::new(|cx
, span
, (self_args
, tag_tuple
), _non_self_args
| {
104 if self_args
.len() != 2 {
105 cx
.span_bug(span
, "not exactly 2 arguments in `derive(Ord)`")
107 ordering_collapsed(cx
, span
, tag_tuple
)