Skip to main content

rustc_builtin_macros/deriving/
ord.rs

1use rustc_expand::base::ExtCtxt;
2use rustc_span::{Span, sym};
3use thin_vec::thin_vec;
4
5use crate::deriving::generic::*;
6use crate::deriving::partial_ord::{OrdlikeDerive, cmp_body, discr_data_order};
7use crate::deriving::path_std;
8
9pub(crate) fn expand_deriving_ord(
10    cx: &ExtCtxt<'_>,
11    span: Span,
12    item: &ast::Item,
13    push: &mut dyn FnMut(Box<ast::Item>),
14    is_const: bool,
15) {
16    let discr_then_data = discr_data_order(item);
17
18    let trait_def = TraitDef {
19        span,
20        path: cx.std_path(span, { &[sym::cmp, sym::Ord] })path_std!(cx, span, cmp::Ord),
21        needs_copy_as_bound_if_packed: true,
22        additional_bounds: SmallVec::new(),
23        supports_unions: false,
24        methods: {
    let count = 0usize + 1usize;
    let mut vec = ::smallvec::SmallVec::new();
    if count <= vec.inline_size() {
        vec.push(MethodDef {
                name: sym::cmp,
                generics: cx.empty_generics(span),
                explicit_self: true,
                nonself_args: {
                    let count = 0usize + 1usize;
                    let mut vec = ::smallvec::SmallVec::new();
                    if count <= vec.inline_size() {
                        vec.push((cx.ty_self_ref(span), sym::other));
                        vec
                    } else {
                        ::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                    [(cx.ty_self_ref(span), sym::other)])))
                    }
                },
                has_other_selflike_arg: true,
                ret_ty: cx.ty_path(cx.std_path(span,
                        { &[sym::cmp, sym::Ordering] })),
                attributes: {
                    let len = [()].len();
                    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
                    vec.push(cx.generated_attr(span,
                            ast::GeneratedAttr::Inline));
                    vec
                },
                fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
                combine_substructure: combine_substructure(|cx, span, substr|
                        cs_cmp(cx, span, substr, discr_then_data)),
            });
        vec
    } else {
        ::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                    [MethodDef {
                                name: sym::cmp,
                                generics: cx.empty_generics(span),
                                explicit_self: true,
                                nonself_args: {
                                    let count = 0usize + 1usize;
                                    let mut vec = ::smallvec::SmallVec::new();
                                    if count <= vec.inline_size() {
                                        vec.push((cx.ty_self_ref(span), sym::other));
                                        vec
                                    } else {
                                        ::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                    [(cx.ty_self_ref(span), sym::other)])))
                                    }
                                },
                                has_other_selflike_arg: true,
                                ret_ty: cx.ty_path(cx.std_path(span,
                                        { &[sym::cmp, sym::Ordering] })),
                                attributes: {
                                    let len = [()].len();
                                    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
                                    vec.push(cx.generated_attr(span,
                                            ast::GeneratedAttr::Inline));
                                    vec
                                },
                                fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
                                combine_substructure: combine_substructure(|cx, span,
                                        substr| cs_cmp(cx, span, substr, discr_then_data)),
                            }])))
    }
}smallvec![MethodDef {
25            name: sym::cmp,
26            generics: cx.empty_generics(span),
27            explicit_self: true,
28            nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)],
29            has_other_selflike_arg: true,
30            ret_ty: cx.ty_path(path_std!(cx, span, cmp::Ordering)),
31            attributes: thin_vec![cx.generated_attr(span, ast::GeneratedAttr::Inline)],
32            fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
33            combine_substructure: combine_substructure(|cx, span, substr| cs_cmp(
34                cx,
35                span,
36                substr,
37                discr_then_data
38            )),
39        }],
40        is_const,
41        ..
42    };
43
44    trait_def.expand(cx, item, push)
45}
46
47pub(crate) fn cs_cmp(
48    cx: &ExtCtxt<'_>,
49    span: Span,
50    substr: Substructure<'_>,
51    discr_then_data: bool,
52) -> BlockOrExpr {
53    // Builds:
54    //
55    // match ::core::cmp::Ord::cmp(&self.x, &other.x) {
56    //     ::std::cmp::Ordering::Equal =>
57    //         ::core::cmp::Ord::cmp(&self.y, &other.y),
58    //     cmp => cmp,
59    // }
60    let expr = cmp_body(cx, span, substr, discr_then_data, OrdlikeDerive::Ord);
61    BlockOrExpr::new_expr(expr)
62}