Skip to content

Commit f365b68

Browse files
committed
Derive PartialOrd::partial_cmp via tuples for mid-sized structs
1 parent 6059387 commit f365b68

File tree

3 files changed

+45
-65
lines changed

3 files changed

+45
-65
lines changed

compiler/rustc_ast/src/ast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2695,6 +2695,8 @@ pub enum VariantData {
26952695
/// Struct variant.
26962696
///
26972697
/// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
2698+
///
2699+
/// The `bool` is `true` if recovery was used while parsing it.
26982700
Struct(ThinVec<FieldDef>, bool),
26992701
/// Tuple variant.
27002702
///

compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
55
use rustc_expand::base::{Annotatable, ExtCtxt};
66
use rustc_span::symbol::{sym, Ident};
77
use rustc_span::Span;
8-
use thin_vec::thin_vec;
8+
use std::ops::Range;
9+
use thin_vec::{thin_vec, ThinVec};
910

1011
pub fn expand_deriving_partial_ord(
1112
cx: &mut ExtCtxt<'_>,
@@ -79,6 +80,13 @@ fn cs_partial_cmp(
7980
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
8081
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
8182

83+
if let SubstructureFields::Struct(_vdata, field_info) = substr.fields {
84+
const FIELD_COUNTS_TO_USE_TUPLES: Range<usize> = 3..13;
85+
if FIELD_COUNTS_TO_USE_TUPLES.contains(&field_info.len()) {
86+
return cs_partial_cmp_via_tuple(cx, span, field_info);
87+
}
88+
}
89+
8290
// Builds:
8391
//
8492
// match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) {
@@ -151,3 +159,29 @@ fn cs_partial_cmp(
151159
);
152160
BlockOrExpr::new_expr(expr)
153161
}
162+
163+
fn cs_partial_cmp_via_tuple(cx: &mut ExtCtxt<'_>, span: Span, fields: &[FieldInfo]) -> BlockOrExpr {
164+
debug_assert!(fields.len() <= 12, "This won't work for more fields than tuples support");
165+
166+
let mut lhs_exprs = ThinVec::with_capacity(fields.len());
167+
let mut rhs_exprs = ThinVec::with_capacity(fields.len());
168+
169+
for field in fields {
170+
lhs_exprs.push(field.self_expr.clone());
171+
// if i + 1 == fields.len() {
172+
// // The last field might need an extra indirection because unsized
173+
// expr = cx.expr_addr_of(field.span, expr);
174+
// };
175+
let [other_expr] = field.other_selflike_exprs.as_slice() else {
176+
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`");
177+
};
178+
rhs_exprs.push(other_expr.clone());
179+
}
180+
181+
let lhs = cx.expr_addr_of(span, cx.expr_tuple(span, lhs_exprs));
182+
let rhs = cx.expr_addr_of(span, cx.expr_tuple(span, rhs_exprs));
183+
184+
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
185+
let call = cx.expr_call_global(span, partial_cmp_path, thin_vec![lhs, rhs]);
186+
BlockOrExpr::new_expr(call)
187+
}

tests/ui/deriving/deriving-all-codegen.stdout

+8-64
Original file line numberDiff line numberDiff line change
@@ -340,47 +340,10 @@ impl ::core::cmp::PartialOrd for Big {
340340
#[inline]
341341
fn partial_cmp(&self, other: &Big)
342342
-> ::core::option::Option<::core::cmp::Ordering> {
343-
match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) {
344-
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
345-
match ::core::cmp::PartialOrd::partial_cmp(&self.b2,
346-
&other.b2) {
347-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
348-
=>
349-
match ::core::cmp::PartialOrd::partial_cmp(&self.b3,
350-
&other.b3) {
351-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
352-
=>
353-
match ::core::cmp::PartialOrd::partial_cmp(&self.b4,
354-
&other.b4) {
355-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
356-
=>
357-
match ::core::cmp::PartialOrd::partial_cmp(&self.b5,
358-
&other.b5) {
359-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
360-
=>
361-
match ::core::cmp::PartialOrd::partial_cmp(&self.b6,
362-
&other.b6) {
363-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
364-
=>
365-
match ::core::cmp::PartialOrd::partial_cmp(&self.b7,
366-
&other.b7) {
367-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
368-
=>
369-
::core::cmp::PartialOrd::partial_cmp(&self.b8, &other.b8),
370-
cmp => cmp,
371-
},
372-
cmp => cmp,
373-
},
374-
cmp => cmp,
375-
},
376-
cmp => cmp,
377-
},
378-
cmp => cmp,
379-
},
380-
cmp => cmp,
381-
},
382-
cmp => cmp,
383-
}
343+
::core::cmp::PartialOrd::partial_cmp(&(&self.b1, &self.b2, &self.b3,
344+
&self.b4, &self.b5, &self.b6, &self.b7, &self.b8),
345+
&(&other.b1, &other.b2, &other.b3, &other.b4, &other.b5,
346+
&other.b6, &other.b7, &other.b8))
384347
}
385348
}
386349
#[automatically_derived]
@@ -622,16 +585,8 @@ impl<T: ::core::cmp::PartialOrd + Trait, U: ::core::cmp::PartialOrd>
622585
#[inline]
623586
fn partial_cmp(&self, other: &Generic<T, U>)
624587
-> ::core::option::Option<::core::cmp::Ordering> {
625-
match ::core::cmp::PartialOrd::partial_cmp(&self.t, &other.t) {
626-
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
627-
match ::core::cmp::PartialOrd::partial_cmp(&self.ta,
628-
&other.ta) {
629-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
630-
=> ::core::cmp::PartialOrd::partial_cmp(&self.u, &other.u),
631-
cmp => cmp,
632-
},
633-
cmp => cmp,
634-
}
588+
::core::cmp::PartialOrd::partial_cmp(&(&self.t, &self.ta, &self.u),
589+
&(&other.t, &other.ta, &other.u))
635590
}
636591
}
637592
#[automatically_derived]
@@ -745,19 +700,8 @@ impl<T: ::core::cmp::PartialOrd + ::core::marker::Copy + Trait,
745700
#[inline]
746701
fn partial_cmp(&self, other: &PackedGeneric<T, U>)
747702
-> ::core::option::Option<::core::cmp::Ordering> {
748-
match ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
749-
{
750-
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
751-
match ::core::cmp::PartialOrd::partial_cmp(&{ self.1 },
752-
&{ other.1 }) {
753-
::core::option::Option::Some(::core::cmp::Ordering::Equal)
754-
=>
755-
::core::cmp::PartialOrd::partial_cmp(&{ self.2 },
756-
&{ other.2 }),
757-
cmp => cmp,
758-
},
759-
cmp => cmp,
760-
}
703+
::core::cmp::PartialOrd::partial_cmp(&(&{ self.0 }, &{ self.1 },
704+
&{ self.2 }), &(&{ other.0 }, &{ other.1 }, &{ other.2 }))
761705
}
762706
}
763707
#[automatically_derived]

0 commit comments

Comments
 (0)