diff options
| author | Yoshua Wuyts <yoshuawuyts@gmail.com> | 2021-10-12 14:18:08 +0200 |
|---|---|---|
| committer | Yoshua Wuyts <yoshuawuyts@gmail.com> | 2021-10-12 17:05:58 +0200 |
| commit | 6941fdc49f0cc68955c07c80f0817b991f4dc495 (patch) | |
| tree | b8c0ed8194c10a6d9c6c119d4b6868d4b076d4b6 | |
| parent | bc6aee51b0d4902bf93fe31665e802b8d2df0bd8 (diff) | |
| download | rust-6941fdc49f0cc68955c07c80f0817b991f4dc495.tar.gz rust-6941fdc49f0cc68955c07c80f0817b991f4dc495.zip | |
impl PartialOrd codegen for tuple records
| -rw-r--r-- | crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs | 37 | ||||
| -rw-r--r-- | crates/ide_assists/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 @@ -676,6 +676,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<core::cmp::Ordering> { + 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( replace_derive_with_manual_impl, 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<ast::Stmt> { + 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::<Option<Vec<ast::Stmt>>>()?; + make::block_expr(stmts.into_iter(), tail).indent(ast::edit::IndentLevel(1)) } Some(ast::FieldList::TupleFieldList(field_list)) => { |
