]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | use crate::deriving::generic::ty::*; |
2 | use crate::deriving::generic::*; | |
3 | use crate::deriving::path_std; | |
064997fb | 4 | use rustc_ast::MetaItem; |
dfeec247 | 5 | use rustc_expand::base::{Annotatable, ExtCtxt}; |
f9f354fc | 6 | use rustc_span::symbol::{sym, Ident}; |
dfeec247 | 7 | use rustc_span::Span; |
f2b60f7d | 8 | use thin_vec::thin_vec; |
dfeec247 XL |
9 | |
10 | pub fn expand_deriving_ord( | |
11 | cx: &mut ExtCtxt<'_>, | |
12 | span: Span, | |
13 | mitem: &MetaItem, | |
14 | item: &Annotatable, | |
15 | push: &mut dyn FnMut(Annotatable), | |
487cf647 | 16 | is_const: bool, |
dfeec247 | 17 | ) { |
487cf647 | 18 | let attrs = thin_vec![cx.attr_word(sym::inline, span)]; |
dfeec247 XL |
19 | let trait_def = TraitDef { |
20 | span, | |
3dfed10e | 21 | path: path_std!(cmp::Ord), |
2b03887a | 22 | skip_path_as_bound: false, |
9ffffee4 | 23 | needs_copy_as_bound_if_packed: true, |
dfeec247 | 24 | additional_bounds: Vec::new(), |
dfeec247 XL |
25 | supports_unions: false, |
26 | methods: vec![MethodDef { | |
3dfed10e XL |
27 | name: sym::cmp, |
28 | generics: Bounds::empty(), | |
064997fb FG |
29 | explicit_self: true, |
30 | nonself_args: vec![(self_ref(), sym::other)], | |
31 | ret_ty: Path(path_std!(cmp::Ordering)), | |
dfeec247 | 32 | attributes: attrs, |
9c376795 | 33 | fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, |
dfeec247 XL |
34 | combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), |
35 | }], | |
36 | associated_types: Vec::new(), | |
487cf647 | 37 | is_const, |
dfeec247 XL |
38 | }; |
39 | ||
40 | trait_def.expand(cx, mitem, item, push) | |
41 | } | |
42 | ||
064997fb | 43 | pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { |
f9f354fc | 44 | let test_id = Ident::new(sym::cmp, span); |
064997fb | 45 | let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); |
dfeec247 XL |
46 | let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); |
47 | ||
48 | // Builds: | |
49 | // | |
064997fb FG |
50 | // match ::core::cmp::Ord::cmp(&self.x, &other.x) { |
51 | // ::std::cmp::Ordering::Equal => | |
52 | // ::core::cmp::Ord::cmp(&self.y, &other.y), | |
53 | // cmp => cmp, | |
dfeec247 | 54 | // } |
064997fb | 55 | let expr = cs_fold( |
dfeec247 XL |
56 | // foldr nests the if-elses correctly, leaving the first field |
57 | // as the outermost one, and the last as the innermost. | |
58 | false, | |
dfeec247 XL |
59 | cx, |
60 | span, | |
61 | substr, | |
064997fb FG |
62 | |cx, fold| match fold { |
63 | CsFold::Single(field) => { | |
64 | let [other_expr] = &field.other_selflike_exprs[..] else { | |
65 | cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); | |
66 | }; | |
9ffffee4 | 67 | let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; |
064997fb FG |
68 | cx.expr_call_global(field.span, cmp_path.clone(), args) |
69 | } | |
70 | CsFold::Combine(span, expr1, expr2) => { | |
71 | let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); | |
72 | let neq_arm = | |
73 | cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); | |
9ffffee4 | 74 | cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) |
064997fb FG |
75 | } |
76 | CsFold::Fieldless => cx.expr_path(equal_path.clone()), | |
77 | }, | |
78 | ); | |
79 | BlockOrExpr::new_expr(expr) | |
dfeec247 | 80 | } |