Repository: actix/actix (language: rust)

Issue:
Implement PartialEq and Eq for WeakAddr
## Expected Behavior
After implementing PartialEq and Eq for `WeakAddr`  we can check if weak references point to the same actor, just as we can with their strong counterparts. Expected behavior

Let `w1`, `w2` be either a pair of `WeakAddr`s

* `w1 == w2` evaluates to `true` if and only if both point to the same actor, regardless of whether the actor reference can be upgraded
* `w1==w2` evaluates to false if and only if `w1` and `w2` reference different actors, regardless of whether the reference can be upgraded

## Current Behavior
Currently, `WeakAddr` does not allow equality comparisons.

## Possible Solution
Implement `PartialEq` and `Eq` on the type by comparing the underlying weak references to the channels.

## Steps to Reproduce (for bugs)
not applicable

## Context
When in possession of only weak addresses to actors it is as useful to compare them for equality as it is for regular, strong addresses. I feel it is useful to add the equality comparisons for the sake of making the weak and strong APIs more intuitive and consistent ([principle of least surprise](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)).

## Your Environment

* Rust Version (I.e, output of `rustc -V`): 1.56.1
* Actix Version: 0.12.0



Discussion / hints:

Fix patch:
diff --git a/actix/CHANGES.md b/actix/CHANGES.md
index 75b722dc1..941c2166b 100644
--- a/actix/CHANGES.md
+++ b/actix/CHANGES.md
@@ -3,15 +3,15 @@
 ## Unreleased - 2021-xx-xx
 ### Changed
 - Updated minimum supported Rust version to 1.49.
-
-### Removed
-- Removed `Resolver` actor [#451]
 - Implement `Clone` for `WeakRecipient` [#518]
 - Extend Sender trait by a downgrade function [#518]
 - Make `WeakSender` trait public rather than crate-public [#518]
 - Add `downgrade` functionality to `Recipient` to obtain a `WeakRecipient` [#518]
 - Add `From` conversion from `Recipient` to `WeakRecipient` [#518]
+- Implement `PartialEq` and `Eq` to `WeakAddr` and `WeakAddressSender` [#523]
 
+### Removed
+- Removed `Resolver` actor [#451]
 
 ## 0.12.0 - 2021-06-06
 ### Added
diff --git a/actix/src/address/channel.rs b/actix/src/address/channel.rs
index dd294a32d..5bfe4d3af 100644
--- a/actix/src/address/channel.rs
+++ b/actix/src/address/channel.rs
@@ -141,6 +141,14 @@ impl<A: Actor> fmt::Debug for WeakAddressSender<A> {
     }
 }
 
+impl<A: Actor> PartialEq for WeakAddressSender<A> {
+    fn eq(&self, other: &Self) -> bool {
+        self.inner.ptr_eq(&other.inner)
+    }
+}
+
+impl<A: Actor> Eq for WeakAddressSender<A> {}
+
 trait AssertKinds: Send + Sync + Clone {}
 
 /// The receiving end of a channel which implements the `Stream` trait.
diff --git a/actix/src/address/mod.rs b/actix/src/address/mod.rs
index cf6739451..6cea98556 100644
--- a/actix/src/address/mod.rs
+++ b/actix/src/address/mod.rs
@@ -234,6 +234,14 @@ impl<A: Actor> fmt::Debug for WeakAddr<A> {
     }
 }
 
+impl<A: Actor> PartialEq for WeakAddr<A> {
+    fn eq(&self, other: &Self) -> bool {
+        self.wtx == other.wtx
+    }
+}
+
+impl<A: Actor> std::cmp::Eq for WeakAddr<A> {}
+
 /// The [`Recipient`] type allows to send one specific message to an actor.
 ///
 /// You can get a recipient using the `Addr::recipient()` method. It is possible
@@ -455,6 +463,7 @@ mod tests {
     }
 
     pub struct SetCounter(usize);
+
     impl Message for SetCounter {
         type Result = ();
     }


Test patch:
diff --git a/actix/tests/test_address.rs b/actix/tests/test_address.rs
index ede05eea2..a3546bbba 100644
--- a/actix/tests/test_address.rs
+++ b/actix/tests/test_address.rs
@@ -224,7 +224,7 @@ fn test_weak_recipient_can_be_cloned() {
             pings, 2,
             "both the weak recipient and its clone must have sent a ping"
         );
-    })
+    });
 }
 
 #[test]
@@ -256,7 +256,54 @@ fn test_recipient_can_be_downgraded() {
             ping_count, 2,
             "weak recipients must not fail to send a message"
         );
-    })
+    });
+}
+
+#[test]
+fn test_weak_addr_partial_equality() {
+    let sys = System::new();
+
+    sys.block_on(async move {
+        let actor1 = MyActor3 {}.start();
+        let actor2 = MyActor3 {}.start();
+
+        let weak1 = actor1.downgrade();
+        let weak1_again = actor1.downgrade();
+        let weak2 = actor2.downgrade();
+
+        // if this stops compiling this means that Add::downgrade
+        // now takes self by value and we must clone before downgrading
+
+        assert!(actor1.connected(), "actor 1 must be alive");
+        assert!(actor2.connected(), "actor 2 must be alive");
+        // the assertions we want to hold for partial equality of weak actor addresses
+        // these assertions must hold whether one or both of the actors are connected or not
+        let check_equality_assertions = || {
+            assert_eq!(weak1, weak1);
+            assert_eq!(weak1, weak1_again);
+            assert_eq!(weak2, weak2);
+
+            assert_ne!(weak1, weak2);
+            assert_ne!(weak1_again, weak2);
+        };
+        check_equality_assertions();
+        // make sure that the same results apply when upgrading weak addr to addr and
+        // comparing strong addresses so the results are intuitive and consistent
+        assert_eq!(weak1.upgrade().unwrap(), weak1.upgrade().unwrap());
+        assert_eq!(weak1.upgrade().unwrap(), weak1_again.upgrade().unwrap());
+        assert_eq!(weak2.upgrade().unwrap(), weak2.upgrade().unwrap());
+        assert_ne!(weak1.upgrade().unwrap(), weak2.upgrade().unwrap());
+        assert_ne!(weak1_again.upgrade().unwrap(), weak2.upgrade().unwrap());
+
+        // now drop one of the actors and make sure the same equality comparisons still hold
+        drop(actor1);
+        assert!(actor2.connected());
+        check_equality_assertions();
+
+        // and drop the second actor as well
+        drop(actor2);
+        check_equality_assertions();
+    });
 }
 
 #[test]