Skip to content

Commit

Permalink
fix: refine fallback case in generated PartialEq impl
Browse files Browse the repository at this point in the history
  • Loading branch information
rami3l committed Dec 7, 2022
1 parent fed74c8 commit 57fb18e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,33 @@ impl PartialEq for Foo {
)
}

#[test]
fn add_custom_impl_partial_eq_single_variant_tuple_enum() {
check_assist(
replace_derive_with_manual_impl,
r#"
//- minicore: eq, derive
#[derive(Partial$0Eq)]
enum Foo {
Bar(String),
}
"#,
r#"
enum Foo {
Bar(String),
}
impl PartialEq for Foo {
$0fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Bar(l0), Self::Bar(r0)) => l0 == r0,
}
}
}
"#,
)
}

#[test]
fn add_custom_impl_partial_eq_partial_tuple_enum() {
check_assist(
Expand Down Expand Up @@ -959,7 +986,7 @@ impl PartialEq for Foo {
match (self, other) {
(Self::Bar(l0), Self::Bar(r0)) => l0 == r0,
(Self::Baz(l0), Self::Baz(r0)) => l0 == r0,
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
_ => false,
}
}
}
Expand Down
17 changes: 15 additions & 2 deletions crates/ide-assists/src/utils/gen_trait_fn_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,10 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
let eq_check =
make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs);

let mut n_cases = 0;
let mut arms = vec![];
for variant in enum_.variant_list()?.variants() {
n_cases += 1;
match variant.field_list() {
// => (Self::Bar { bin: l_bin }, Self::Bar { bin: r_bin }) => l_bin == r_bin,
Some(ast::FieldList::RecordFieldList(list)) => {
Expand Down Expand Up @@ -514,8 +516,19 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {

let expr = match arms.len() {
0 => eq_check,
_ => {
arms.push(make::match_arm(Some(make::wildcard_pat().into()), None, eq_check));
arms_len => {
// Generate the fallback arm when this enum has >1 variants.
// The fallback arm will be `_ => false,` if we've already gone through every case where the variants of self and other match,
// and `_ => std::mem::discriminant(self) == std::mem::discriminant(other),` otherwise.
if n_cases > 1 {
let lhs = make::wildcard_pat().into();
let rhs = if arms_len == n_cases {
make::expr_literal("false").into()
} else {
eq_check
};
arms.push(make::match_arm(Some(lhs), None, rhs));
}

let match_target = make::expr_tuple(vec![lhs_name, rhs_name]);
let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1));
Expand Down

0 comments on commit 57fb18e

Please sign in to comment.