]>
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), | |
487cf647 | 16 | is_const: bool, |
dfeec247 | 17 | ) { |
064997fb FG |
18 | let ordering_ty = Path(path_std!(cmp::Ordering)); |
19 | let ret_ty = | |
20 | Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); | |
d9579d0f | 21 | |
487cf647 | 22 | let attrs = thin_vec![cx.attr_word(sym::inline, span)]; |
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), |
2b03887a | 40 | skip_path_as_bound: false, |
d9579d0f | 41 | additional_bounds: vec![], |
9e0c209e | 42 | supports_unions: false, |
6a06907d | 43 | methods: vec![partial_cmp_def], |
d9579d0f | 44 | associated_types: Vec::new(), |
487cf647 | 45 | is_const, |
d9579d0f | 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 | } |