Skip to content

Commit 8420999

Browse files
committed
Auto merge of rust-lang#7316 - lengyijun:rc_mutex, r=llogiq
Add new lint: `rc_mutex` changelog: Add new lint `rc_mutex`. It lints on `Rc<Mutex<T>>`. `Rc<Mutex<T>>` should be corrected to `Rc<RefCell<T>>`
2 parents 2abeac1 + b9cc2fe commit 8420999

File tree

6 files changed

+124
-1
lines changed

6 files changed

+124
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,6 +2744,7 @@ Released 2018-09-13
27442744
[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
27452745
[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len
27462746
[`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer
2747+
[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex
27472748
[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
27482749
[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
27492750
[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
944944
types::LINKEDLIST,
945945
types::OPTION_OPTION,
946946
types::RC_BUFFER,
947+
types::RC_MUTEX,
947948
types::REDUNDANT_ALLOCATION,
948949
types::TYPE_COMPLEXITY,
949950
types::VEC_BOX,
@@ -1042,6 +1043,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10421043
LintId::of(strings::STRING_TO_STRING),
10431044
LintId::of(strings::STR_TO_STRING),
10441045
LintId::of(types::RC_BUFFER),
1046+
LintId::of(types::RC_MUTEX),
10451047
LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
10461048
LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
10471049
LintId::of(verbose_file_reads::VERBOSE_FILE_READS),

clippy_lints/src/types/mod.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod box_vec;
33
mod linked_list;
44
mod option_option;
55
mod rc_buffer;
6+
mod rc_mutex;
67
mod redundant_allocation;
78
mod type_complexity;
89
mod utils;
@@ -250,12 +251,41 @@ declare_clippy_lint! {
250251
"usage of very complex types that might be better factored into `type` definitions"
251252
}
252253

254+
declare_clippy_lint! {
255+
/// **What it does:** Checks for `Rc<Mutex<T>>`.
256+
///
257+
/// **Why is this bad?** `Rc` is used in single thread and `Mutex` is used in multi thread.
258+
/// Consider using `Rc<RefCell<T>>` in single thread or `Arc<Mutex<T>>` in multi thread.
259+
///
260+
/// **Known problems:** Sometimes combining generic types can lead to the requirement that a
261+
/// type use Rc in conjunction with Mutex. We must consider those cases false positives, but
262+
/// alas they are quite hard to rule out. Luckily they are also rare.
263+
///
264+
/// **Example:**
265+
/// ```rust,ignore
266+
/// use std::rc::Rc;
267+
/// use std::sync::Mutex;
268+
/// fn foo(interned: Rc<Mutex<i32>>) { ... }
269+
/// ```
270+
///
271+
/// Better:
272+
///
273+
/// ```rust,ignore
274+
/// use std::rc::Rc;
275+
/// use std::cell::RefCell
276+
/// fn foo(interned: Rc<RefCell<i32>>) { ... }
277+
/// ```
278+
pub RC_MUTEX,
279+
restriction,
280+
"usage of `Rc<Mutex<T>>`"
281+
}
282+
253283
pub struct Types {
254284
vec_box_size_threshold: u64,
255285
type_complexity_threshold: u64,
256286
}
257287

258-
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, TYPE_COMPLEXITY]);
288+
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
259289

260290
impl<'tcx> LateLintPass<'tcx> for Types {
261291
fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
@@ -375,6 +405,7 @@ impl Types {
375405
triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
376406
triggered |= option_option::check(cx, hir_ty, qpath, def_id);
377407
triggered |= linked_list::check(cx, hir_ty, def_id);
408+
triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
378409

379410
if triggered {
380411
return;

clippy_lints/src/types/rc_mutex.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use clippy_utils::is_ty_param_diagnostic_item;
3+
use if_chain::if_chain;
4+
use rustc_hir::{self as hir, def_id::DefId, QPath};
5+
use rustc_lint::LateContext;
6+
use rustc_span::symbol::sym;
7+
8+
use super::RC_MUTEX;
9+
10+
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
11+
if_chain! {
12+
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ;
13+
if let Some(_) = is_ty_param_diagnostic_item(cx, qpath, sym!(mutex_type)) ;
14+
15+
then{
16+
span_lint(
17+
cx,
18+
RC_MUTEX,
19+
hir_ty.span,
20+
"found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
21+
);
22+
return true;
23+
}
24+
}
25+
26+
false
27+
}

tests/ui/rc_mutex.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#![warn(clippy::rc_mutex)]
2+
#![allow(clippy::blacklisted_name)]
3+
4+
use std::rc::Rc;
5+
use std::sync::Mutex;
6+
7+
pub struct MyStruct {
8+
foo: Rc<Mutex<i32>>,
9+
}
10+
11+
pub struct SubT<T> {
12+
foo: T,
13+
}
14+
15+
pub enum MyEnum {
16+
One,
17+
Two,
18+
}
19+
20+
pub fn test1<T>(foo: Rc<Mutex<T>>) {}
21+
22+
pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
23+
24+
pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
25+
26+
fn main() {
27+
test1(Rc::new(Mutex::new(1)));
28+
test2(Rc::new(Mutex::new(MyEnum::One)));
29+
test3(Rc::new(Mutex::new(SubT { foo: 1 })));
30+
31+
let _my_struct = MyStruct {
32+
foo: Rc::new(Mutex::new(1)),
33+
};
34+
}

tests/ui/rc_mutex.stderr

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
2+
--> $DIR/rc_mutex.rs:8:10
3+
|
4+
LL | foo: Rc<Mutex<i32>>,
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::rc-mutex` implied by `-D warnings`
8+
9+
error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
10+
--> $DIR/rc_mutex.rs:20:22
11+
|
12+
LL | pub fn test1<T>(foo: Rc<Mutex<T>>) {}
13+
| ^^^^^^^^^^^^
14+
15+
error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
16+
--> $DIR/rc_mutex.rs:22:19
17+
|
18+
LL | pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
19+
| ^^^^^^^^^^^^^^^^^
20+
21+
error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
22+
--> $DIR/rc_mutex.rs:24:19
23+
|
24+
LL | pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
25+
| ^^^^^^^^^^^^^^^^^^^^^^
26+
27+
error: aborting due to 4 previous errors
28+

0 commit comments

Comments
 (0)