Skip to content

Commit 57fb18e

Browse files
committed
fix: refine fallback case in generated PartialEq impl
1 parent fed74c8 commit 57fb18e

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,33 @@ impl PartialEq for Foo {
906906
)
907907
}
908908

909+
#[test]
910+
fn add_custom_impl_partial_eq_single_variant_tuple_enum() {
911+
check_assist(
912+
replace_derive_with_manual_impl,
913+
r#"
914+
//- minicore: eq, derive
915+
#[derive(Partial$0Eq)]
916+
enum Foo {
917+
Bar(String),
918+
}
919+
"#,
920+
r#"
921+
enum Foo {
922+
Bar(String),
923+
}
924+
925+
impl PartialEq for Foo {
926+
$0fn eq(&self, other: &Self) -> bool {
927+
match (self, other) {
928+
(Self::Bar(l0), Self::Bar(r0)) => l0 == r0,
929+
}
930+
}
931+
}
932+
"#,
933+
)
934+
}
935+
909936
#[test]
910937
fn add_custom_impl_partial_eq_partial_tuple_enum() {
911938
check_assist(
@@ -959,7 +986,7 @@ impl PartialEq for Foo {
959986
match (self, other) {
960987
(Self::Bar(l0), Self::Bar(r0)) => l0 == r0,
961988
(Self::Baz(l0), Self::Baz(r0)) => l0 == r0,
962-
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
989+
_ => false,
963990
}
964991
}
965992
}

crates/ide-assists/src/utils/gen_trait_fn_body.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,10 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
439439
let eq_check =
440440
make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs);
441441

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

515517
let expr = match arms.len() {
516518
0 => eq_check,
517-
_ => {
518-
arms.push(make::match_arm(Some(make::wildcard_pat().into()), None, eq_check));
519+
arms_len => {
520+
// Generate the fallback arm when this enum has >1 variants.
521+
// The fallback arm will be `_ => false,` if we've already gone through every case where the variants of self and other match,
522+
// and `_ => std::mem::discriminant(self) == std::mem::discriminant(other),` otherwise.
523+
if n_cases > 1 {
524+
let lhs = make::wildcard_pat().into();
525+
let rhs = if arms_len == n_cases {
526+
make::expr_literal("false").into()
527+
} else {
528+
eq_check
529+
};
530+
arms.push(make::match_arm(Some(lhs), None, rhs));
531+
}
519532

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

0 commit comments

Comments
 (0)