]>
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}; |
9cc50fc6 | 4 | |
064997fb | 5 | use rustc_ast::MetaItem; |
dfeec247 | 6 | use rustc_expand::base::{Annotatable, ExtCtxt}; |
6a06907d | 7 | use rustc_span::symbol::{sym, Ident}; |
dfeec247 | 8 | use rustc_span::Span; |
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); |
416331ca | 22 | let attrs = 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, |
d9579d0f | 39 | attributes: vec![], |
3dfed10e | 40 | path: path_std!(cmp::PartialOrd), |
d9579d0f | 41 | additional_bounds: vec![], |
3dfed10e | 42 | generics: Bounds::empty(), |
9e0c209e | 43 | supports_unions: false, |
6a06907d | 44 | methods: vec![partial_cmp_def], |
d9579d0f AL |
45 | associated_types: Vec::new(), |
46 | }; | |
62682a34 | 47 | trait_def.expand(cx, mitem, item, push) |
d9579d0f AL |
48 | } |
49 | ||
064997fb | 50 | pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { |
f9f354fc | 51 | let test_id = Ident::new(sym::cmp, span); |
064997fb | 52 | let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); |
dc9dc135 | 53 | let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]); |
d9579d0f | 54 | |
5bcae85e SL |
55 | // Builds: |
56 | // | |
064997fb FG |
57 | // match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { |
58 | // ::core::option::Option::Some(::core::cmp::Ordering::Equal) => | |
59 | // ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), | |
60 | // cmp => cmp, | |
5bcae85e | 61 | // } |
064997fb | 62 | let expr = cs_fold( |
dfeec247 XL |
63 | // foldr nests the if-elses correctly, leaving the first field |
64 | // as the outermost one, and the last as the innermost. | |
65 | false, | |
dfeec247 XL |
66 | cx, |
67 | span, | |
68 | substr, | |
064997fb FG |
69 | |cx, fold| match fold { |
70 | CsFold::Single(field) => { | |
71 | let [other_expr] = &field.other_selflike_exprs[..] else { | |
72 | cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); | |
73 | }; | |
74 | let args = vec![field.self_expr.clone(), other_expr.clone()]; | |
75 | cx.expr_call_global(field.span, partial_cmp_path.clone(), args) | |
76 | } | |
77 | CsFold::Combine(span, expr1, expr2) => { | |
78 | let eq_arm = | |
79 | cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1); | |
80 | let neq_arm = | |
81 | cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); | |
82 | cx.expr_match(span, expr2, vec![eq_arm, neq_arm]) | |
83 | } | |
84 | CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())), | |
85 | }, | |
86 | ); | |
87 | BlockOrExpr::new_expr(expr) | |
d9579d0f | 88 | } |