From 6941fdc49f0cc68955c07c80f0817b991f4dc495 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Tue, 12 Oct 2021 14:18:08 +0200 Subject: [PATCH] impl PartialOrd codegen for tuple records --- .../replace_derive_with_manual_impl.rs | 37 +++++++++++++++++++ .../src/utils/gen_trait_fn_body.rs | 37 +++++++++++++++++-- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs index c0b7db332e2..1dc8dd95abd 100644 --- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs @@ -675,6 +675,43 @@ impl Clone for Foo { ) } + #[test] + fn add_custom_impl_partial_ord_record_struct() { + check_assist( + replace_derive_with_manual_impl, + r#" +//- minicore: ord +#[derive(Partial$0Ord)] +struct Foo { + bin: usize, + bar: usize, + baz: usize, +} +"#, + r#" +struct Foo { + bin: usize, + bar: usize, + baz: usize, +} + +impl PartialOrd for Foo { + $0fn partial_cmp(&self, other: &Self) -> Option { + match self.bin.partial_cmp(other.bin) { + Some(core::cmp::Ordering::Eq) => {} + ord => return ord, + } + match self.bar.partial_cmp(other.bar) { + Some(core::cmp::Ordering::Eq) => {} + ord => return ord, + } + self.baz.partial_cmp(other.baz) + } +} +"#, + ) + } + #[test] fn add_custom_impl_partial_eq_record_struct() { check_assist( diff --git a/crates/ide_assists/src/utils/gen_trait_fn_body.rs b/crates/ide_assists/src/utils/gen_trait_fn_body.rs index 5ec8adc2d4c..aa0d9bc76bd 100644 --- a/crates/ide_assists/src/utils/gen_trait_fn_body.rs +++ b/crates/ide_assists/src/utils/gen_trait_fn_body.rs @@ -581,6 +581,29 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { } } + fn gen_partial_eq_match(match_target: ast::Expr) -> Option { + let mut arms = vec![]; + + let variant_name = + make::path_pat(make::ext::path_from_idents(["core", "cmp", "Ordering", "Eq"])?); + let lhs = make::tuple_struct_pat(make::ext::path_from_idents(["Some"])?, [variant_name]); + arms.push(make::match_arm(Some(lhs.into()), None, make::expr_empty_block())); + + arms.push(make::match_arm( + [make::ident_pat(false, false, make::name("ord")).into()], + None, + make::expr_return(Some(make::expr_path(make::ext::ident_path("ord")))), + )); + // let rhs = make::expr_path(make::ext::ident_path("other")); + let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); + Some(make::expr_stmt(make::expr_match(match_target, list)).into()) + } + + fn gen_partial_cmp_call(lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr { + let method = make::name_ref("partial_cmp"); + make::expr_method_call(lhs, method, make::arg_list(Some(rhs))) + } + fn gen_record_pat_field(field_name: &str, pat_name: &str) -> ast::RecordPatField { let pat = make::ext::simple_ident_pat(make::name(&pat_name)); let name_ref = make::name_ref(field_name); @@ -700,16 +723,22 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { } ast::Adt::Struct(strukt) => match strukt.field_list() { Some(ast::FieldList::RecordFieldList(field_list)) => { - let mut expr = None; + let mut exprs = vec![]; for field in field_list.fields() { let lhs = make::expr_path(make::ext::ident_path("self")); let lhs = make::expr_field(lhs, &field.name()?.to_string()); let rhs = make::expr_path(make::ext::ident_path("other")); let rhs = make::expr_field(rhs, &field.name()?.to_string()); - let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs); - expr = gen_eq_chain(expr, cmp); + let ord = gen_partial_cmp_call(lhs, rhs); + exprs.push(ord); } - make::block_expr(None, expr).indent(ast::edit::IndentLevel(1)) + + let tail = exprs.pop(); + let stmts = exprs + .into_iter() + .map(gen_partial_eq_match) + .collect::>>()?; + make::block_expr(stmts.into_iter(), tail).indent(ast::edit::IndentLevel(1)) } Some(ast::FieldList::TupleFieldList(field_list)) => {