|
1 |
| -use rustc_lint::LateLintPass; |
| 1 | +use clippy_utils::{diagnostics::span_lint_and_sugg, ty::implements_trait}; |
| 2 | +use rustc_errors::Applicability; |
| 3 | +use rustc_hir::{intravisit::FnKind, Body, FnDecl, FnRetTy, HirId}; |
| 4 | +use rustc_lint::{LateContext, LateLintPass}; |
2 | 5 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
| 6 | +use rustc_span::Span; |
| 7 | +use rustc_typeck::hir_ty_to_ty; |
3 | 8 |
|
4 | 9 | declare_clippy_lint! {
|
5 | 10 | /// ### What it does
|
@@ -29,4 +34,39 @@ declare_clippy_lint! {
|
29 | 34 | }
|
30 | 35 | declare_lint_pass!(UnusedBox => [UNUSED_BOX]);
|
31 | 36 |
|
32 |
| -impl LateLintPass<'_> for UnusedBox {} |
| 37 | +impl LateLintPass<'_> for UnusedBox { |
| 38 | + fn check_fn( |
| 39 | + &mut self, |
| 40 | + cx: &LateContext<'_>, |
| 41 | + fn_kind: FnKind<'_>, |
| 42 | + decl: &FnDecl<'_>, |
| 43 | + _: &Body<'_>, |
| 44 | + _: Span, |
| 45 | + _: HirId, |
| 46 | + ) { |
| 47 | + if let FnKind::Closure = fn_kind { |
| 48 | + return; |
| 49 | + } |
| 50 | + let FnRetTy::Return(return_ty_hir) = &decl.output else { return }; |
| 51 | + let return_ty = hir_ty_to_ty(cx.tcx, return_ty_hir); |
| 52 | + |
| 53 | + if !return_ty.is_box() { |
| 54 | + return; |
| 55 | + } |
| 56 | + |
| 57 | + let boxed_ty = return_ty.boxed_ty(); |
| 58 | + let Some(sized_trait) = cx.tcx.lang_items().sized_trait() else { return }; |
| 59 | + |
| 60 | + if implements_trait(cx, boxed_ty, sized_trait, &[]) { |
| 61 | + span_lint_and_sugg( |
| 62 | + cx, |
| 63 | + UNUSED_BOX, |
| 64 | + return_ty_hir.span, |
| 65 | + format!("function returns `Box<{0}>` when `{0}` implements `Sized`", boxed_ty).as_str(), |
| 66 | + "change the return type to", |
| 67 | + boxed_ty.to_string(), |
| 68 | + Applicability::MaybeIncorrect, |
| 69 | + ); |
| 70 | + } |
| 71 | + } |
| 72 | +} |
0 commit comments