Skip to content

Commit

Permalink
Derive PartialOrd::partial_cmp via tuples for mid-sized structs
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmcm committed Feb 27, 2023
1 parent 6059387 commit f365b68
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 65 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2695,6 +2695,8 @@ pub enum VariantData {
/// Struct variant.
///
/// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
///
/// The `bool` is `true` if recovery was used while parsing it.
Struct(ThinVec<FieldDef>, bool),
/// Tuple variant.
///
Expand Down
36 changes: 35 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use thin_vec::thin_vec;
use std::ops::Range;
use thin_vec::{thin_vec, ThinVec};

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

if let SubstructureFields::Struct(_vdata, field_info) = substr.fields {
const FIELD_COUNTS_TO_USE_TUPLES: Range<usize> = 3..13;
if FIELD_COUNTS_TO_USE_TUPLES.contains(&field_info.len()) {
return cs_partial_cmp_via_tuple(cx, span, field_info);
}
}

// Builds:
//
// match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) {
Expand Down Expand Up @@ -151,3 +159,29 @@ fn cs_partial_cmp(
);
BlockOrExpr::new_expr(expr)
}

fn cs_partial_cmp_via_tuple(cx: &mut ExtCtxt<'_>, span: Span, fields: &[FieldInfo]) -> BlockOrExpr {
debug_assert!(fields.len() <= 12, "This won't work for more fields than tuples support");

let mut lhs_exprs = ThinVec::with_capacity(fields.len());
let mut rhs_exprs = ThinVec::with_capacity(fields.len());

for field in fields {
lhs_exprs.push(field.self_expr.clone());
// if i + 1 == fields.len() {
// // The last field might need an extra indirection because unsized
// expr = cx.expr_addr_of(field.span, expr);
// };
let [other_expr] = field.other_selflike_exprs.as_slice() else {
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`");
};
rhs_exprs.push(other_expr.clone());
}

let lhs = cx.expr_addr_of(span, cx.expr_tuple(span, lhs_exprs));
let rhs = cx.expr_addr_of(span, cx.expr_tuple(span, rhs_exprs));

let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
let call = cx.expr_call_global(span, partial_cmp_path, thin_vec![lhs, rhs]);
BlockOrExpr::new_expr(call)
}
72 changes: 8 additions & 64 deletions tests/ui/deriving/deriving-all-codegen.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -340,47 +340,10 @@ impl ::core::cmp::PartialOrd for Big {
#[inline]
fn partial_cmp(&self, other: &Big)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&self.b2,
&other.b2) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
match ::core::cmp::PartialOrd::partial_cmp(&self.b3,
&other.b3) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
match ::core::cmp::PartialOrd::partial_cmp(&self.b4,
&other.b4) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
match ::core::cmp::PartialOrd::partial_cmp(&self.b5,
&other.b5) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
match ::core::cmp::PartialOrd::partial_cmp(&self.b6,
&other.b6) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
match ::core::cmp::PartialOrd::partial_cmp(&self.b7,
&other.b7) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
::core::cmp::PartialOrd::partial_cmp(&self.b8, &other.b8),
cmp => cmp,
},
cmp => cmp,
},
cmp => cmp,
},
cmp => cmp,
},
cmp => cmp,
},
cmp => cmp,
},
cmp => cmp,
}
::core::cmp::PartialOrd::partial_cmp(&(&self.b1, &self.b2, &self.b3,
&self.b4, &self.b5, &self.b6, &self.b7, &self.b8),
&(&other.b1, &other.b2, &other.b3, &other.b4, &other.b5,
&other.b6, &other.b7, &other.b8))
}
}
#[automatically_derived]
Expand Down Expand Up @@ -622,16 +585,8 @@ impl<T: ::core::cmp::PartialOrd + Trait, U: ::core::cmp::PartialOrd>
#[inline]
fn partial_cmp(&self, other: &Generic<T, U>)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.t, &other.t) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&self.ta,
&other.ta) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=> ::core::cmp::PartialOrd::partial_cmp(&self.u, &other.u),
cmp => cmp,
},
cmp => cmp,
}
::core::cmp::PartialOrd::partial_cmp(&(&self.t, &self.ta, &self.u),
&(&other.t, &other.ta, &other.u))
}
}
#[automatically_derived]
Expand Down Expand Up @@ -745,19 +700,8 @@ impl<T: ::core::cmp::PartialOrd + ::core::marker::Copy + Trait,
#[inline]
fn partial_cmp(&self, other: &PackedGeneric<T, U>)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
{
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&{ self.1 },
&{ other.1 }) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
::core::cmp::PartialOrd::partial_cmp(&{ self.2 },
&{ other.2 }),
cmp => cmp,
},
cmp => cmp,
}
::core::cmp::PartialOrd::partial_cmp(&(&{ self.0 }, &{ self.1 },
&{ self.2 }), &(&{ other.0 }, &{ other.1 }, &{ other.2 }))
}
}
#[automatically_derived]
Expand Down

0 comments on commit f365b68

Please sign in to comment.