Skip to content

Commit 8c8014d

Browse files
committed
support Rc
1 parent cfdab81 commit 8c8014d

15 files changed

+105
-16
lines changed

clippy_lints/src/arc_new_in_vec_from_elem.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::macros::{root_macro_call_first_node, MacroCall};
55
use rustc_hir::{Expr, ExprKind, QPath, TyKind};
66
use rustc_lint::{LateContext, LateLintPass};
77
use rustc_session::{declare_lint_pass, declare_tool_lint};
8-
use rustc_span::sym;
8+
use rustc_span::{sym, Symbol};
99

1010
declare_clippy_lint! {
1111
/// ### What it does
@@ -37,43 +37,46 @@ impl LateLintPass<'_> for ArcNewInVecFromElem {
3737
let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return; };
3838

3939
if let Some(VecArgs::Repeat(elem, _)) = VecArgs::hir(cx, expr) {
40-
if !is_arc_new(cx, elem) {
41-
return;
42-
}
40+
let Some(symbol) = new_reference_call(cx, elem) else { return; };
4341

44-
yield_lint(cx, &macro_call);
42+
yield_lint(cx, symbol, &macro_call);
4543
}
4644
}
4745
}
4846

49-
fn yield_lint(cx: &LateContext<'_>, macro_call: &MacroCall) {
47+
fn yield_lint(cx: &LateContext<'_>, symbol: Symbol, macro_call: &MacroCall) {
48+
let symbol_name = symbol.as_str();
49+
5050
span_lint_and_then(
5151
cx,
5252
ARC_NEW_IN_VEC_FROM_ELEM,
5353
macro_call.span,
54-
"calling `Arc::new` in `vec![elem; len]`",
54+
&format!("calling `{symbol_name}::new` in `vec![elem; len]`"),
5555
|diag| {
56-
diag.note("each `Arc` will point to the same allocation");
57-
diag.help("if this is intentional, consider extracting the `Arc` initialization to a variable");
56+
diag.note(format!("each `{symbol_name}` will point to the same allocation"));
57+
diag.help(format!(
58+
"if this is intentional, consider extracting the `{symbol_name}` initialization to a variable"
59+
));
5860
},
5961
);
6062
}
6163

62-
/// Checks whether the given `expr` is a call to `Arc::new`
63-
fn is_arc_new(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
64+
/// Checks whether the given `expr` is a call to `Arc::new` or `Rc::new`
65+
fn new_reference_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
6466
if_chain! {
6567
if let ExprKind::Call(func, _args) = expr.kind;
6668
if let ExprKind::Path(ref func_path @ QPath::TypeRelative(ty, _)) = func.kind;
6769
if let TyKind::Path(ref ty_path) = ty.kind;
6870
if let Some(def_id) = cx.qpath_res(ty_path, ty.hir_id).opt_def_id();
69-
if cx.tcx.is_diagnostic_item(sym::Arc, def_id);
71+
if last_path_segment(func_path).ident.name == sym::new;
7072

7173
then {
72-
let func_segment = last_path_segment(func_path);
73-
74-
return func_segment.ident.name == sym::new;
74+
return match cx.tcx.get_diagnostic_name(def_id) {
75+
Some(symbol) if symbol == sym::Arc || symbol == sym::Rc => Some(symbol),
76+
_ => None
77+
};
7578
}
7679
}
7780

78-
false
81+
None
7982
}
File renamed without changes.

tests/ui/arc_new_in_vec_from_elem/complex_case.stderr renamed to tests/ui/arc_new_in_vec_from_elem/arc/complex_case.stderr

File renamed without changes.

tests/ui/arc_new_in_vec_from_elem/custom_arc_strucrt.rs renamed to tests/ui/arc_new_in_vec_from_elem/arc/custom_arc_strucrt.rs

File renamed without changes.
File renamed without changes.

tests/ui/arc_new_in_vec_from_elem/simple_case.stderr renamed to tests/ui/arc_new_in_vec_from_elem/arc/simple_case.stderr

File renamed without changes.

tests/ui/arc_new_in_vec_from_elem/vec_from_elem_but_not_arc.rs renamed to tests/ui/arc_new_in_vec_from_elem/arc/vec_from_elem_but_not_arc.rs

File renamed without changes.

tests/ui/arc_new_in_vec_from_elem/vec_macro_but_not_from_elem.rs renamed to tests/ui/arc_new_in_vec_from_elem/arc/vec_macro_but_not_from_elem.rs

File renamed without changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![warn(clippy::arc_new_in_vec_from_elem)]
2+
use std::sync::Mutex;
3+
4+
fn main() {
5+
let v = vec![
6+
std::rc::Rc::new(Mutex::new({
7+
let x = 1;
8+
dbg!(x);
9+
x
10+
}));
11+
2
12+
];
13+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error: calling `Rc::new` in `vec![elem; len]`
2+
--> $DIR/complex_case.rs:5:13
3+
|
4+
LL | let v = vec![
5+
| _____________^
6+
LL | | std::rc::Rc::new(Mutex::new({
7+
LL | | let x = 1;
8+
LL | | dbg!(x);
9+
... |
10+
LL | | 2
11+
LL | | ];
12+
| |_____^
13+
|
14+
= note: `-D clippy::arc-new-in-vec-from-elem` implied by `-D warnings`
15+
= note: each `Rc` will point to the same allocation
16+
= help: if this is intentional, consider extracting the `Rc` initialization to a variable
17+
18+
error: aborting due to previous error
19+

0 commit comments

Comments
 (0)