Skip to content

Commit ad71930

Browse files
committed
redundant_allocation: check Rc and Arc in same block
1 parent 29d917a commit ad71930

File tree

5 files changed

+111
-112
lines changed

5 files changed

+111
-112
lines changed

clippy_lints/src/types/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ declare_clippy_lint! {
177177
declare_clippy_lint! {
178178
/// **What it does:** Checks for use of redundant allocations anywhere in the code.
179179
///
180-
/// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Box<T>>`, Arc<&T>`, `Arc<Arc<T>>`,
181-
/// `Arc<Box<T>>`, `Box<&T>` add an unnecessary level of indirection.
180+
/// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, Arc<&T>`, `Arc<Rc<T>>`,
181+
/// `Arc<Arc<T>>`, `Arc<Box<T>>`, `Box<&T>` add an unnecessary level of indirection.
182182
///
183183
/// **Known problems:** None.
184184
///

clippy_lints/src/types/redundant_allocation.rs

Lines changed: 38 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -25,71 +25,40 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
2525
}
2626
}
2727

28-
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
29-
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Rc) {
30-
let mut applicability = Applicability::MachineApplicable;
31-
span_lint_and_sugg(
32-
cx,
33-
REDUNDANT_ALLOCATION,
34-
hir_ty.span,
35-
"usage of `Rc<Rc<T>>`",
36-
"try",
37-
snippet_with_applicability(cx, ty.span, "..", &mut applicability).to_string(),
38-
applicability,
39-
);
40-
return true;
41-
} else if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
42-
let qpath = match &ty.kind {
43-
TyKind::Path(qpath) => qpath,
44-
_ => return false,
45-
};
46-
let inner_span = match get_qpath_generic_tys(qpath).next() {
47-
Some(ty) => ty.span,
48-
None => return false,
49-
};
50-
let mut applicability = Applicability::MachineApplicable;
51-
span_lint_and_sugg(
52-
cx,
53-
REDUNDANT_ALLOCATION,
54-
hir_ty.span,
55-
"usage of `Rc<Box<T>>`",
56-
"try",
57-
format!(
58-
"Rc<{}>",
59-
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
60-
),
61-
applicability,
62-
);
63-
return true;
64-
}
65-
return utils::match_borrows_parameter(cx, qpath).map_or(false, |span| {
66-
let mut applicability = Applicability::MachineApplicable;
67-
span_lint_and_sugg(
68-
cx,
69-
REDUNDANT_ALLOCATION,
70-
hir_ty.span,
71-
"usage of `Rc<&T>`",
72-
"try",
73-
snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
74-
applicability,
75-
);
76-
true
77-
});
78-
}
28+
let sym_outer = if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
29+
Some(sym::Rc)
30+
} else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
31+
Some(sym::Arc)
32+
} else {
33+
None
34+
};
7935

80-
if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
81-
if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Arc) {
82-
let mut applicability = Applicability::MachineApplicable;
83-
span_lint_and_sugg(
84-
cx,
85-
REDUNDANT_ALLOCATION,
86-
hir_ty.span,
87-
"usage of `Arc<Arc<T>>`",
88-
"try",
89-
snippet_with_applicability(cx, ty.span, "..", &mut applicability).to_string(),
90-
applicability,
91-
);
92-
return true;
36+
if let Some(sym_outer) = sym_outer {
37+
let ty = is_ty_param_diagnostic_item(cx, qpath, sym::Rc)
38+
.map_or_else(|| is_ty_param_diagnostic_item(cx, qpath, sym::Arc), |ty| Some(ty));
39+
40+
if let Some(ty) = ty {
41+
if let TyKind::Path(ref qpath_inner) = ty.kind {
42+
let inner_span = match get_qpath_generic_tys(qpath_inner).next() {
43+
Some(ty) => ty.span,
44+
None => return false,
45+
};
46+
let mut applicability = Applicability::MachineApplicable;
47+
span_lint_and_sugg(
48+
cx,
49+
REDUNDANT_ALLOCATION,
50+
hir_ty.span,
51+
&format!("usage of `{}<Rc<T>>`", sym_outer),
52+
"try",
53+
format!(
54+
"{}<{}>",
55+
sym_outer,
56+
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
57+
),
58+
applicability,
59+
);
60+
return true;
61+
}
9362
} else if let Some(ty) = is_ty_param_lang_item(cx, qpath, LangItem::OwnedBox) {
9463
let qpath = match &ty.kind {
9564
TyKind::Path(qpath) => qpath,
@@ -104,10 +73,11 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
10473
cx,
10574
REDUNDANT_ALLOCATION,
10675
hir_ty.span,
107-
"usage of `Arc<Box<T>>`",
76+
&format!("usage of `{}<Box<T>>`", sym_outer),
10877
"try",
10978
format!(
110-
"Arc<{}>",
79+
"{}<{}>",
80+
sym_outer,
11181
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
11282
),
11383
applicability,
@@ -120,13 +90,14 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
12090
cx,
12191
REDUNDANT_ALLOCATION,
12292
hir_ty.span,
123-
"usage of `Arc<&T>`",
93+
&format!("usage of `{}<&T>`", sym_outer),
12494
"try",
12595
snippet_with_applicability(cx, span, "..", &mut applicability).to_string(),
12696
applicability,
12797
);
12898
true
12999
});
130100
}
101+
131102
false
132103
}

tests/ui/redundant_allocation.fixed

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,36 +32,44 @@ pub fn test4_neg(foo: Rc<SubT<&usize>>) {}
3232

3333
pub fn test5(a: Rc<bool>) {}
3434

35-
// Rc<Box<T>>
35+
// Rc<Arc<T>>
3636

3737
pub fn test6(a: Rc<bool>) {}
3838

39+
// Rc<Box<T>>
40+
41+
pub fn test7(a: Rc<bool>) {}
42+
3943
// Box<&T>
4044

41-
pub fn test7<T>(foo: &T) {}
45+
pub fn test8<T>(foo: &T) {}
4246

43-
pub fn test8(foo: &MyStruct) {}
47+
pub fn test9(foo: &MyStruct) {}
4448

45-
pub fn test9(foo: &MyEnum) {}
49+
pub fn test10(foo: &MyEnum) {}
4650

47-
pub fn test10_neg(foo: Box<SubT<&usize>>) {}
51+
pub fn test11_neg(foo: Box<SubT<&usize>>) {}
4852

4953
// Arc<&T>
5054

51-
pub fn test11<T>(foo: &T) {}
55+
pub fn test12<T>(foo: &T) {}
5256

53-
pub fn test12(foo: &MyStruct) {}
57+
pub fn test13(foo: &MyStruct) {}
5458

55-
pub fn test13(foo: &MyEnum) {}
59+
pub fn test14(foo: &MyEnum) {}
5660

57-
pub fn test14_neg(foo: Arc<SubT<&usize>>) {}
61+
pub fn test15_neg(foo: Arc<SubT<&usize>>) {}
62+
63+
// Arc<Rc<T>>
64+
65+
pub fn test16(a: Arc<bool>) {}
5866

5967
// Arc<Arc<T>>
6068

61-
pub fn test15(a: Arc<bool>) {}
69+
pub fn test17(a: Arc<bool>) {}
6270

6371
// Arc<Box<T>>
6472

65-
pub fn test16(a: Arc<bool>) {}
73+
pub fn test18(a: Arc<bool>) {}
6674

6775
fn main() {}

tests/ui/redundant_allocation.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,36 +32,44 @@ pub fn test4_neg(foo: Rc<SubT<&usize>>) {}
3232

3333
pub fn test5(a: Rc<Rc<bool>>) {}
3434

35+
// Rc<Arc<T>>
36+
37+
pub fn test6(a: Rc<Arc<bool>>) {}
38+
3539
// Rc<Box<T>>
3640

37-
pub fn test6(a: Rc<Box<bool>>) {}
41+
pub fn test7(a: Rc<Box<bool>>) {}
3842

3943
// Box<&T>
4044

41-
pub fn test7<T>(foo: Box<&T>) {}
45+
pub fn test8<T>(foo: Box<&T>) {}
4246

43-
pub fn test8(foo: Box<&MyStruct>) {}
47+
pub fn test9(foo: Box<&MyStruct>) {}
4448

45-
pub fn test9(foo: Box<&MyEnum>) {}
49+
pub fn test10(foo: Box<&MyEnum>) {}
4650

47-
pub fn test10_neg(foo: Box<SubT<&usize>>) {}
51+
pub fn test11_neg(foo: Box<SubT<&usize>>) {}
4852

4953
// Arc<&T>
5054

51-
pub fn test11<T>(foo: Arc<&T>) {}
55+
pub fn test12<T>(foo: Arc<&T>) {}
56+
57+
pub fn test13(foo: Arc<&MyStruct>) {}
58+
59+
pub fn test14(foo: Arc<&MyEnum>) {}
5260

53-
pub fn test12(foo: Arc<&MyStruct>) {}
61+
pub fn test15_neg(foo: Arc<SubT<&usize>>) {}
5462

55-
pub fn test13(foo: Arc<&MyEnum>) {}
63+
// Arc<Rc<T>>
5664

57-
pub fn test14_neg(foo: Arc<SubT<&usize>>) {}
65+
pub fn test16(a: Arc<Rc<bool>>) {}
5866

5967
// Arc<Arc<T>>
6068

61-
pub fn test15(a: Arc<Arc<bool>>) {}
69+
pub fn test17(a: Arc<Arc<bool>>) {}
6270

6371
// Arc<Box<T>>
6472

65-
pub fn test16(a: Arc<Box<bool>>) {}
73+
pub fn test18(a: Arc<Box<bool>>) {}
6674

6775
fn main() {}

tests/ui/redundant_allocation.stderr

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,59 +24,71 @@ error: usage of `Rc<Rc<T>>`
2424
LL | pub fn test5(a: Rc<Rc<bool>>) {}
2525
| ^^^^^^^^^^^^ help: try: `Rc<bool>`
2626

27-
error: usage of `Rc<Box<T>>`
27+
error: usage of `Rc<Rc<T>>`
2828
--> $DIR/redundant_allocation.rs:37:17
2929
|
30-
LL | pub fn test6(a: Rc<Box<bool>>) {}
30+
LL | pub fn test6(a: Rc<Arc<bool>>) {}
31+
| ^^^^^^^^^^^^^ help: try: `Rc<bool>`
32+
33+
error: usage of `Rc<Box<T>>`
34+
--> $DIR/redundant_allocation.rs:41:17
35+
|
36+
LL | pub fn test7(a: Rc<Box<bool>>) {}
3137
| ^^^^^^^^^^^^^ help: try: `Rc<bool>`
3238

3339
error: usage of `Box<&T>`
34-
--> $DIR/redundant_allocation.rs:41:22
40+
--> $DIR/redundant_allocation.rs:45:22
3541
|
36-
LL | pub fn test7<T>(foo: Box<&T>) {}
42+
LL | pub fn test8<T>(foo: Box<&T>) {}
3743
| ^^^^^^^ help: try: `&T`
3844

3945
error: usage of `Box<&T>`
40-
--> $DIR/redundant_allocation.rs:43:19
46+
--> $DIR/redundant_allocation.rs:47:19
4147
|
42-
LL | pub fn test8(foo: Box<&MyStruct>) {}
48+
LL | pub fn test9(foo: Box<&MyStruct>) {}
4349
| ^^^^^^^^^^^^^^ help: try: `&MyStruct`
4450

4551
error: usage of `Box<&T>`
46-
--> $DIR/redundant_allocation.rs:45:19
52+
--> $DIR/redundant_allocation.rs:49:20
4753
|
48-
LL | pub fn test9(foo: Box<&MyEnum>) {}
49-
| ^^^^^^^^^^^^ help: try: `&MyEnum`
54+
LL | pub fn test10(foo: Box<&MyEnum>) {}
55+
| ^^^^^^^^^^^^ help: try: `&MyEnum`
5056

5157
error: usage of `Arc<&T>`
52-
--> $DIR/redundant_allocation.rs:51:23
58+
--> $DIR/redundant_allocation.rs:55:23
5359
|
54-
LL | pub fn test11<T>(foo: Arc<&T>) {}
60+
LL | pub fn test12<T>(foo: Arc<&T>) {}
5561
| ^^^^^^^ help: try: `&T`
5662

5763
error: usage of `Arc<&T>`
58-
--> $DIR/redundant_allocation.rs:53:20
64+
--> $DIR/redundant_allocation.rs:57:20
5965
|
60-
LL | pub fn test12(foo: Arc<&MyStruct>) {}
66+
LL | pub fn test13(foo: Arc<&MyStruct>) {}
6167
| ^^^^^^^^^^^^^^ help: try: `&MyStruct`
6268

6369
error: usage of `Arc<&T>`
64-
--> $DIR/redundant_allocation.rs:55:20
70+
--> $DIR/redundant_allocation.rs:59:20
6571
|
66-
LL | pub fn test13(foo: Arc<&MyEnum>) {}
72+
LL | pub fn test14(foo: Arc<&MyEnum>) {}
6773
| ^^^^^^^^^^^^ help: try: `&MyEnum`
6874

69-
error: usage of `Arc<Arc<T>>`
70-
--> $DIR/redundant_allocation.rs:61:18
75+
error: usage of `Arc<Rc<T>>`
76+
--> $DIR/redundant_allocation.rs:65:18
7177
|
72-
LL | pub fn test15(a: Arc<Arc<bool>>) {}
78+
LL | pub fn test16(a: Arc<Rc<bool>>) {}
79+
| ^^^^^^^^^^^^^ help: try: `Arc<bool>`
80+
81+
error: usage of `Arc<Rc<T>>`
82+
--> $DIR/redundant_allocation.rs:69:18
83+
|
84+
LL | pub fn test17(a: Arc<Arc<bool>>) {}
7385
| ^^^^^^^^^^^^^^ help: try: `Arc<bool>`
7486

7587
error: usage of `Arc<Box<T>>`
76-
--> $DIR/redundant_allocation.rs:65:18
88+
--> $DIR/redundant_allocation.rs:73:18
7789
|
78-
LL | pub fn test16(a: Arc<Box<bool>>) {}
90+
LL | pub fn test18(a: Arc<Box<bool>>) {}
7991
| ^^^^^^^^^^^^^^ help: try: `Arc<bool>`
8092

81-
error: aborting due to 13 previous errors
93+
error: aborting due to 15 previous errors
8294

0 commit comments

Comments
 (0)