about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/arc_with_non_send_sync.rs22
-rw-r--r--tests/ui/arc_with_non_send_sync.rs6
-rw-r--r--tests/ui/arc_with_non_send_sync.stderr32
3 files changed, 37 insertions, 23 deletions
diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs
index 192bc7d9ddc..9799e703afe 100644
--- a/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/clippy_lints/src/arc_with_non_send_sync.rs
@@ -14,7 +14,9 @@ declare_clippy_lint! {
     /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`.
     ///
     /// ### Why is this bad?
-    /// `Arc<T>` is only `Send`/`Sync` when `T` is [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E),
+    /// `Arc<T>` is an Atomic `RC<T>` and guarantees that updates to the reference counter are
+    /// Atomic. This is useful in multiprocessing scenarios. To send an `Arc<T>` across processes
+    /// and make use of the atomic ref counter, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E),
     /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
     ///
     /// ### Example
@@ -34,7 +36,7 @@ declare_clippy_lint! {
     #[clippy::version = "1.72.0"]
     pub ARC_WITH_NON_SEND_SYNC,
     suspicious,
-    "using `Arc` with a type that does not implement `Send` or `Sync`"
+    "using `Arc` with a type that does not implement `Send` and `Sync`"
 }
 declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]);
 
@@ -61,19 +63,25 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
                 cx,
                 ARC_WITH_NON_SEND_SYNC,
                 expr.span,
-                "usage of an `Arc` that is not `Send` or `Sync`",
+                "usage of an `Arc` that is not `Send` and `Sync`",
                 |diag| {
                     with_forced_trimmed_paths!({
+                        diag.note(format!("`Arc<{arg_ty}>` is not `Send` and `Sync` as:"));
+
                         if !is_send {
-                            diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`"));
+                            diag.note(format!("- the trait `Send` is not implemented for `{arg_ty}`"));
                         }
                         if !is_sync {
-                            diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`"));
+                            diag.note(format!("- the trait `Sync` is not implemented for `{arg_ty}`"));
                         }
 
-                        diag.note(format!("required for `{ty}` to implement `Send` and `Sync`"));
+                        diag.help("consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types");
+
+                        diag.note("if you intend to use `Arc` with `Send` and `Sync` traits");
 
-                        diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`");
+                        diag.note(format!(
+                            "wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `{arg_ty}`"
+                        ));
                     });
                 },
             );
diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs
index d03a577c454..349e81912e3 100644
--- a/tests/ui/arc_with_non_send_sync.rs
+++ b/tests/ui/arc_with_non_send_sync.rs
@@ -33,16 +33,16 @@ fn main() {
     let _ = Arc::new(42);
 
     let _ = Arc::new(RefCell::new(42));
-    //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync`
+    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
     //~| NOTE: the trait `Sync` is not implemented for `RefCell<i32>`
 
     let mutex = Mutex::new(1);
     let _ = Arc::new(mutex.lock().unwrap());
-    //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync`
+    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
     //~| NOTE: the trait `Send` is not implemented for `MutexGuard<'_, i32>`
 
     let _ = Arc::new(&42 as *const i32);
-    //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync`
+    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
     //~| NOTE: the trait `Send` is not implemented for `*const i32`
     //~| NOTE: the trait `Sync` is not implemented for `*const i32`
 }
diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr
index fd239580d28..a7f91abda4e 100644
--- a/tests/ui/arc_with_non_send_sync.stderr
+++ b/tests/ui/arc_with_non_send_sync.stderr
@@ -1,35 +1,41 @@
-error: usage of an `Arc` that is not `Send` or `Sync`
+error: usage of an `Arc` that is not `Send` and `Sync`
   --> $DIR/arc_with_non_send_sync.rs:35:13
    |
 LL |     let _ = Arc::new(RefCell::new(42));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the trait `Sync` is not implemented for `RefCell<i32>`
-   = note: required for `Arc<RefCell<i32>>` to implement `Send` and `Sync`
-   = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
+   = note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as:
+   = note: - the trait `Sync` is not implemented for `RefCell<i32>`
+   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
+   = note: if you intend to use `Arc` with `Send` and `Sync` traits
+   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `RefCell<i32>`
    = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]`
 
-error: usage of an `Arc` that is not `Send` or `Sync`
+error: usage of an `Arc` that is not `Send` and `Sync`
   --> $DIR/arc_with_non_send_sync.rs:40:13
    |
 LL |     let _ = Arc::new(mutex.lock().unwrap());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the trait `Send` is not implemented for `MutexGuard<'_, i32>`
-   = note: required for `Arc<MutexGuard<'_, i32>>` to implement `Send` and `Sync`
-   = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
+   = note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as:
+   = note: - the trait `Send` is not implemented for `MutexGuard<'_, i32>`
+   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
+   = note: if you intend to use `Arc` with `Send` and `Sync` traits
+   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `MutexGuard<'_, i32>`
 
-error: usage of an `Arc` that is not `Send` or `Sync`
+error: usage of an `Arc` that is not `Send` and `Sync`
   --> $DIR/arc_with_non_send_sync.rs:44:13
    |
 LL |     let _ = Arc::new(&42 as *const i32);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the trait `Send` is not implemented for `*const i32`
-   = note: the trait `Sync` is not implemented for `*const i32`
-   = note: required for `Arc<*const i32>` to implement `Send` and `Sync`
-   = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
+   = note: `Arc<*const i32>` is not `Send` and `Sync` as:
+   = note: - the trait `Send` is not implemented for `*const i32`
+   = note: - the trait `Sync` is not implemented for `*const i32`
+   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
+   = note: if you intend to use `Arc` with `Send` and `Sync` traits
+   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `*const i32`
 
 error: aborting due to 3 previous errors