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