diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 7adcd9ad055..35a04b5e44a 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::last_path_segment; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::{is_from_proc_macro, last_path_segment}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -38,10 +38,11 @@ } declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); -impl LateLintPass<'_> for ArcWithNonSendSync { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - let ty = cx.typeck_results().expr_ty(expr); - if is_type_diagnostic_item(cx, ty, sym::Arc) +impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if !expr.span.from_expansion() + && let ty = cx.typeck_results().expr_ty(expr) + && is_type_diagnostic_item(cx, ty, sym::Arc) && let ExprKind::Call(func, [arg]) = expr.kind && let ExprKind::Path(func_path) = func.kind && last_path_segment(&func_path).ident.name == sym::new @@ -54,6 +55,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { && let Some(sync) = cx.tcx.lang_items().sync_trait() && let [is_send, is_sync] = [send, sync].map(|id| implements_trait(cx, arg_ty, id, &[])) && !(is_send && is_sync) + && !is_from_proc_macro(cx, expr) { span_lint_and_then( cx, diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs index b6fcca0a791..2940c273255 100644 --- a/tests/ui/arc_with_non_send_sync.rs +++ b/tests/ui/arc_with_non_send_sync.rs @@ -1,6 +1,12 @@ +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::arc_with_non_send_sync)] #![allow(unused_variables)] + +#[macro_use] +extern crate proc_macros; + use std::cell::RefCell; +use std::ptr::{null, null_mut}; use std::sync::{Arc, Mutex}; fn foo(x: T) { @@ -11,14 +17,32 @@ fn issue11076() { let a: Arc> = Arc::new(Vec::new()); } +fn issue11232() { + external! { + let a: Arc<*const u8> = Arc::new(null()); + let a: Arc<*mut u8> = Arc::new(null_mut()); + } + with_span! { + span + let a: Arc<*const u8> = Arc::new(null()); + let a: Arc<*mut u8> = Arc::new(null_mut()); + } +} + fn main() { let _ = Arc::new(42); - // !Sync let _ = Arc::new(RefCell::new(42)); + //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync` + //~| NOTE: the trait `Sync` is not implemented for `RefCell` + let mutex = Mutex::new(1); - // !Send let _ = Arc::new(mutex.lock().unwrap()); - // !Send + !Sync + //~^ ERROR: usage of an `Arc` that is not `Send` or `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` + //~| 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 7633b38dfb5..de3f2fb9e16 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -1,5 +1,5 @@ error: usage of an `Arc` that is not `Send` or `Sync` - --> $DIR/arc_with_non_send_sync.rs:18:13 + --> $DIR/arc_with_non_send_sync.rs:35:13 | LL | let _ = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | let _ = Arc::new(RefCell::new(42)); = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` error: usage of an `Arc` that is not `Send` or `Sync` - --> $DIR/arc_with_non_send_sync.rs:21:13 + --> $DIR/arc_with_non_send_sync.rs:40:13 | LL | let _ = Arc::new(mutex.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | let _ = Arc::new(mutex.lock().unwrap()); = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` error: usage of an `Arc` that is not `Send` or `Sync` - --> $DIR/arc_with_non_send_sync.rs:23:13 + --> $DIR/arc_with_non_send_sync.rs:44:13 | LL | let _ = Arc::new(&42 as *const i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^