|
1 |
| -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; |
| 1 | +use clippy_utils::diagnostics::span_lint_and_help; |
2 | 2 | use clippy_utils::source::snippet_with_applicability;
|
3 | 3 | use clippy_utils::ty::implements_trait;
|
| 4 | +use clippy_utils::visitors::is_const_evaluatable; |
4 | 5 | use hir::{BindingMode, ExprKind, PatKind, Stmt, StmtKind};
|
5 | 6 | use rustc_errors::Applicability;
|
6 | 7 | use rustc_hir as hir;
|
@@ -38,58 +39,73 @@ declare_clippy_lint! {
|
38 | 39 |
|
39 | 40 | declare_lint_pass!(LetArrConst => [LET_ARR_CONST]);
|
40 | 41 |
|
41 |
| -impl LateLintPass<'_> for LetArrConst { |
42 |
| - // should lint on `let array` which non-mut and: |
43 |
| - // if let repeat: |
44 |
| - // if let expr: copy |
45 |
| - // todo: repair clippy::author |
46 |
| - fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { |
47 |
| - if let StmtKind::Let(ref local) = stmt.kind |
| 42 | +// FIXME: See also LARGE_CONST_ARRAYS, LARGE_STACK_ARRAYS. |
| 43 | +impl<'tcx> LateLintPass<'tcx> for LetArrConst { |
| 44 | + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { |
| 45 | + // let pat: ty = init; |
| 46 | + if let StmtKind::Let(local) = stmt.kind |
48 | 47 | && let PatKind::Binding(BindingMode::NONE, _, _name, None) = local.pat.kind
|
49 |
| - && let Some(ref init) = local.init |
| 48 | + && let Some(init) = local.init |
50 | 49 | && !init.span.from_expansion()
|
51 | 50 | {
|
| 51 | + const STACK_THRESHOLD: u64 = 16; |
| 52 | + // lint only `if size_of(init) > STACK_THRESHOLD` |
| 53 | + let ty = cx.typeck_results().expr_ty(init); |
| 54 | + if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) |
| 55 | + && let size = layout.layout.size() |
| 56 | + && size.bytes() <= STACK_THRESHOLD |
| 57 | + { |
| 58 | + return; |
| 59 | + } |
| 60 | + |
52 | 61 | let mut applicability = Applicability::MachineApplicable;
|
53 | 62 | let lang_items = cx.tcx.lang_items();
|
54 | 63 | let Some(copy_id) = lang_items.copy_trait() else {
|
55 | 64 | return;
|
56 | 65 | };
|
57 |
| - // `let arr = [<Copy type>; 42]; |
| 66 | + |
| 67 | + let generic_msg = "using `static` to push the array to read-only section of program"; |
| 68 | + let report_static = || { |
| 69 | + span_lint_and_help( |
| 70 | + cx, |
| 71 | + LET_ARR_CONST, |
| 72 | + local.span, |
| 73 | + "declaring a read-only array on the stack", |
| 74 | + None, |
| 75 | + generic_msg, |
| 76 | + ); |
| 77 | + }; |
| 78 | + |
| 79 | + // `if init is [<Copy type>; 42] |
58 | 80 | let mut should = false;
|
59 |
| - if let ExprKind::Repeat(ref value, _length) = init.kind { |
| 81 | + if let ExprKind::Repeat(value, _length) = init.kind { |
60 | 82 | let ty = cx.typeck_results().expr_ty(value);
|
61 | 83 | if !implements_trait(cx, ty, copy_id, &[]) {
|
62 |
| - span_lint_and_help( |
63 |
| - cx, |
64 |
| - LET_ARR_CONST, |
65 |
| - local.span, |
66 |
| - "declaring a read-only array on the stack", |
67 |
| - None, |
68 |
| - "using `static` to push the array to read-only section of program", |
69 |
| - ); |
| 84 | + report_static(); |
70 | 85 | return;
|
71 | 86 | }
|
72 | 87 | should = true;
|
73 | 88 | }
|
74 |
| - // `let arr = [1, 2, 3, 4]; |
75 |
| - if let ExprKind::Array([ref expr, ..]) = init.kind |
| 89 | + // `if init is [1, 2, 3, 4] |
| 90 | + if let ExprKind::Array(items @ [ref expr, ..]) = init.kind |
76 | 91 | && let ty = cx.typeck_results().expr_ty(expr)
|
77 | 92 | && implements_trait(cx, ty, copy_id, &[])
|
78 | 93 | {
|
79 |
| - should = true; |
| 94 | + if items.iter().all(|expr| is_const_evaluatable(cx, expr)) { |
| 95 | + should = true; |
| 96 | + } |
80 | 97 | }
|
81 | 98 |
|
82 | 99 | if should {
|
83 | 100 | let snippet = snippet_with_applicability(cx, init.span, "_", &mut applicability);
|
84 |
| - let sugg = format!("*&{snippet}"); |
85 |
| - span_lint_and_sugg( |
| 101 | + let msg = format!("{generic_msg} or try: `*&{snippet}`"); |
| 102 | + span_lint_and_help( |
86 | 103 | cx,
|
87 | 104 | LET_ARR_CONST,
|
88 | 105 | init.span,
|
89 | 106 | "declaring a read-only array on the stack",
|
90 |
| - "using `static` to push the array to read-only section of program or try", |
91 |
| - sugg, |
92 |
| - applicability, |
| 107 | + None, |
| 108 | + msg, |
93 | 109 | );
|
94 | 110 | }
|
95 | 111 | }
|
|
0 commit comments