[arc_with_non_send_sync]: Check if it's macro-generated

This commit is contained in:
Catherine Flores 2023-07-25 17:56:43 -05:00
parent 2153c0fcc8
commit 90947e95ad
3 changed files with 37 additions and 11 deletions

View File

@ -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,

View File

@ -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<T>(x: T) {
@ -11,14 +17,32 @@ fn issue11076<T>() {
let a: Arc<Vec<T>> = 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<i32>`
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`
}

View File

@ -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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^