]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/functions/result_unit_err.rs
Merge commit '97a5daa65908e59744e2bc625b14849352231c75' into clippyup
[rust.git] / clippy_lints / src / functions / result_unit_err.rs
1 use rustc_hir as hir;
2 use rustc_lint::{LateContext, LintContext};
3 use rustc_middle::lint::in_external_macro;
4 use rustc_middle::ty;
5 use rustc_span::{sym, Span};
6 use rustc_typeck::hir_ty_to_ty;
7
8 use if_chain::if_chain;
9
10 use clippy_utils::diagnostics::span_lint_and_help;
11 use clippy_utils::trait_ref_of_method;
12 use clippy_utils::ty::is_type_diagnostic_item;
13
14 use super::RESULT_UNIT_ERR;
15
16 pub(super) fn check_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
17     if let hir::ItemKind::Fn(ref sig, ref _generics, _) = item.kind {
18         let is_public = cx.access_levels.is_exported(item.def_id);
19         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
20         if is_public {
21             check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
22         }
23     }
24 }
25
26 pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &hir::ImplItem<'_>) {
27     if let hir::ImplItemKind::Fn(ref sig, _) = item.kind {
28         let is_public = cx.access_levels.is_exported(item.def_id);
29         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
30         if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() {
31             check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
32         }
33     }
34 }
35
36 pub(super) fn check_trait_item(cx: &LateContext<'_>, item: &hir::TraitItem<'_>) {
37     if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
38         let is_public = cx.access_levels.is_exported(item.def_id);
39         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
40         if is_public {
41             check_result_unit_err(cx, sig.decl, item.span, fn_header_span);
42         }
43     }
44 }
45
46 fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) {
47     if_chain! {
48         if !in_external_macro(cx.sess(), item_span);
49         if let hir::FnRetTy::Return(ty) = decl.output;
50         let ty = hir_ty_to_ty(cx.tcx, ty);
51         if is_type_diagnostic_item(cx, ty, sym::Result);
52         if let ty::Adt(_, substs) = ty.kind();
53         let err_ty = substs.type_at(1);
54         if err_ty.is_unit();
55         then {
56             span_lint_and_help(
57                 cx,
58                 RESULT_UNIT_ERR,
59                 fn_header_span,
60                 "this returns a `Result<_, ()>`",
61                 None,
62                 "use a custom `Error` type instead",
63             );
64         }
65     }
66 }