Repository: rust-lang/rust-analyzer (rust)

Issue:
Implement default members implements PartialEq::ne incorrectly
rust-analyzer version: rust-analyzer 0.0.0 (https://github.com/rust-lang/rust-analyzer/commit/5342f47f4276641ddb5f0a5e08fb307742d6cdc4 2022-07-09)

rustc version: rustc 1.62.0 (a8314ef7d 2022-06-27)

relevant settings: Neovim with coc-rust-analyzer

I tried `implement default members` on some code by mistake, but got surprising results. Reproduction:

```rust
struct SomeStruct {
    data: Arc<Vec<u8>>,
    field: (u32, u32),
}

impl PartialEq for SomeStruct {
}
```

It will generate this `ne` method:

```rust
impl PartialEq for SomeStruct {
    fn ne(&self, other: &Self) -> bool {
        self.data == other.data && self.field == other.field
    }
}
```

The `implement missing members` works as expected for `eq`


Pull request description:
fix: Correctly generate default `PartialEq::ne`
Fixes #12779 

For the `Generate default members` assist on the `PartialEq` trait, the assist will now give the default implementation instead of generating a function.

Patch:
diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 573c362c81..6e6fd96a68 100644
--- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -1305,4 +1305,30 @@ impl Trait<u32> for Impl {
 }"#,
         );
     }
+
+    #[test]
+    fn test_default_partial_eq() {
+        check_assist(
+            add_missing_default_members,
+            r#"
+//- minicore: eq
+struct SomeStruct {
+    data: usize,
+    field: (usize, usize),
+}
+impl PartialEq for SomeStruct {$0}
+"#,
+            r#"
+struct SomeStruct {
+    data: usize,
+    field: (usize, usize),
+}
+impl PartialEq for SomeStruct {
+    $0fn ne(&self, other: &Self) -> bool {
+            !self.eq(other)
+        }
+}
+"#,
+        );
+    }
 }
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 30b994806b..ec4835969f 100644
--- a/crates/ide-assists/src/utils/gen_trait_fn_body.rs
+++ b/crates/ide-assists/src/utils/gen_trait_fn_body.rs
@@ -394,6 +394,9 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
 
 /// Generate a `PartialEq` impl based on the fields and members of the target type.
 fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
+    if func.name().map_or(false, |name| name.text() == "ne") {
+        return None;
+    }
     fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
         match expr {
             Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)),
@@ -424,7 +427,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
     // generate this code `Self` for the time being.
 
     let body = match adt {
-        // `Hash` cannot be derived for unions, so no default impl can be provided.
+        // `PartialEq` cannot be derived for unions, so no default impl can be provided.
         ast::Adt::Union(_) => return None,
 
         ast::Adt::Enum(enum_) => {


Test patch:
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 8474014a2c..f48d1ec66a 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -354,6 +354,9 @@ pub mod cmp {
     #[lang = "eq"]
     pub trait PartialEq<Rhs: ?Sized = Self> {
         fn eq(&self, other: &Rhs) -> bool;
+        fn ne(&self, other: &Rhs) -> bool {
+            !self.eq(other)
+        }
     }
 
     pub trait Eq: PartialEq<Self> {}