Skip to content

Commit c0f3c2f

Browse files
author
lyj
committed
correct lint
1 parent 84c511f commit c0f3c2f

File tree

7 files changed

+127
-10
lines changed

7 files changed

+127
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,6 +2611,7 @@ Released 2018-09-13
26112611
[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
26122612
[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len
26132613
[`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer
2614+
[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex
26142615
[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
26152616
[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
26162617
[`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
@@ -931,6 +931,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
931931
types::LINKEDLIST,
932932
types::OPTION_OPTION,
933933
types::RC_BUFFER,
934+
types::RC_MUTEX,
934935
types::REDUNDANT_ALLOCATION,
935936
types::TYPE_COMPLEXITY,
936937
types::VEC_BOX,
@@ -1027,6 +1028,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10271028
LintId::of(strings::STRING_TO_STRING),
10281029
LintId::of(strings::STR_TO_STRING),
10291030
LintId::of(types::RC_BUFFER),
1031+
LintId::of(types::RC_MUTEX),
10301032
LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
10311033
LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
10321034
LintId::of(verbose_file_reads::VERBOSE_FILE_READS),

clippy_lints/src/types/mod.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ 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;
910
mod vec_box;
10-
mod rc_mutex;
1111

1212
use rustc_hir as hir;
1313
use rustc_hir::intravisit::FnKind;
@@ -252,18 +252,50 @@ declare_clippy_lint! {
252252
}
253253

254254
declare_clippy_lint! {
255-
/// TODO
255+
/// **What it does:** Checks for `Rc<Mutex<T>>`.
256+
///
257+
/// **Why is this bad?** `Rc<Mutex<T>>` may introduce a deadlock in single thread. Consider
258+
/// using `Rc<RefCell<T>>` instead.
259+
/// ```rust
260+
/// fn main() {
261+
/// use std::rc::Rc;
262+
/// use std::sync::Mutex;
263+
///
264+
/// let a: Rc<Mutex<i32>> = Rc::new(Mutex::new(1));
265+
/// let a_clone = a.clone();
266+
/// let mut data = a.lock().unwrap();
267+
/// println!("{:?}", *a_clone.lock().unwrap());
268+
/// *data = 10;
269+
/// }
270+
/// ```
271+
///
272+
/// **Known problems:** `Rc<RefCell<T>>` may panic in runtime.
273+
///
274+
/// **Example:**
275+
/// ```rust,ignore
276+
/// use std::rc::Rc;
277+
/// use std::sync::Mutex;
278+
/// fn foo(interned: Rc<Mutex<i32>>) { ... }
279+
/// ```
280+
///
281+
/// Better:
282+
///
283+
/// ```rust,ignore
284+
/// use std::rc::Rc;
285+
/// use std::cell::RefCell
286+
/// fn foo(interned: Rc<RefCell<i32>>) { ... }
287+
/// ```
256288
pub RC_MUTEX,
257289
restriction,
258-
"usage of Mutex inside Rc"
290+
"usage of `Rc<Mutex<T>>`"
259291
}
260292

261293
pub struct Types {
262294
vec_box_size_threshold: u64,
263295
type_complexity_threshold: u64,
264296
}
265297

266-
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, TYPE_COMPLEXITY,RC_MUTEX]);
298+
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
267299

268300
impl<'tcx> LateLintPass<'tcx> for Types {
269301
fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {

clippy_lints/src/types/rc_mutex.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::{ get_qpath_generic_tys,is_ty_param_diagnostic_item};
32
use clippy_utils::source::snippet_with_applicability;
3+
use clippy_utils::{get_qpath_generic_tys, is_ty_param_diagnostic_item};
4+
use if_chain::if_chain;
45
use rustc_errors::Applicability;
5-
use rustc_hir::{self as hir, def_id::DefId, QPath};
6+
use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
67
use rustc_lint::LateContext;
78
use rustc_span::symbol::sym;
8-
// use rustc_middle::ty::Adt;
99

1010
use super::RC_MUTEX;
1111

1212
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
13-
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
14-
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym!(mutex_type)) {
13+
if_chain! {
14+
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ;
15+
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym!(mutex_type)) ;
16+
if let TyKind::Path(ref qpath_inner)=ty.kind;
17+
18+
then{
1519
let mut applicability = Applicability::MachineApplicable;
1620

17-
let inner_span = match get_qpath_generic_tys(qpath).skip(1).next() {
21+
let inner_span = match get_qpath_generic_tys(qpath_inner).next() {
1822
Some(ty) => ty.span,
1923
None => return false,
2024
};

tests/ui/rc_mutex.fixed

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// run-rustfix
2+
#![warn(clippy::rc_mutex)]
3+
#![allow(unused_imports)]
4+
#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
5+
#![allow(clippy::blacklisted_name, unused_variables, dead_code)]
6+
7+
use std::cell::RefCell;
8+
use std::rc::Rc;
9+
use std::sync::Mutex;
10+
11+
pub struct MyStruct {}
12+
13+
pub struct SubT<T> {
14+
foo: T,
15+
}
16+
17+
pub enum MyEnum {
18+
One,
19+
Two,
20+
}
21+
22+
pub fn test1<T>(foo: Rc<RefCell<T>>) {}
23+
24+
pub fn test2(foo: Rc<RefCell<MyEnum>>) {}
25+
26+
pub fn test3(foo: Rc<RefCell<SubT<usize>>>) {}
27+
28+
fn main() {}

tests/ui/rc_mutex.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// run-rustfix
2+
#![warn(clippy::rc_mutex)]
3+
#![allow(unused_imports)]
4+
#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
5+
#![allow(clippy::blacklisted_name, unused_variables, dead_code)]
6+
7+
use std::cell::RefCell;
8+
use std::rc::Rc;
9+
use std::sync::Mutex;
10+
11+
pub struct MyStruct {}
12+
13+
pub struct SubT<T> {
14+
foo: T,
15+
}
16+
17+
pub enum MyEnum {
18+
One,
19+
Two,
20+
}
21+
22+
pub fn test1<T>(foo: Rc<Mutex<T>>) {}
23+
24+
pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
25+
26+
pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
27+
28+
fn main() {}

tests/ui/rc_mutex.stderr

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

0 commit comments

Comments
 (0)