]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | //! lint when there is an enum with no variants |
2 | ||
3 | use crate::utils::span_lint_and_help; | |
4 | use rustc_hir::{Item, ItemKind}; | |
5 | use rustc_lint::{LateContext, LateLintPass}; | |
6 | use rustc_session::{declare_lint_pass, declare_tool_lint}; | |
7 | ||
8 | declare_clippy_lint! { | |
9 | /// **What it does:** Checks for `enum`s with no variants. | |
10 | /// | |
11 | /// As of this writing, the `never_type` is still a | |
12 | /// nightly-only experimental API. Therefore, this lint is only triggered | |
13 | /// if the `never_type` is enabled. | |
14 | /// | |
15 | /// **Why is this bad?** If you want to introduce a type which | |
16 | /// can't be instantiated, you should use `!` (the primitive type "never"), | |
17 | /// or a wrapper around it, because `!` has more extensive | |
18 | /// compiler support (type inference, etc...) and wrappers | |
19 | /// around it are the conventional way to define an uninhabited type. | |
20 | /// For further information visit [never type documentation](https://doc.rust-lang.org/std/primitive.never.html) | |
21 | /// | |
22 | /// | |
23 | /// **Known problems:** None. | |
24 | /// | |
25 | /// **Example:** | |
26 | /// | |
27 | /// Bad: | |
28 | /// ```rust | |
29 | /// enum Test {} | |
30 | /// ``` | |
31 | /// | |
32 | /// Good: | |
33 | /// ```rust | |
34 | /// #![feature(never_type)] | |
35 | /// | |
36 | /// struct Test(!); | |
37 | /// ``` | |
38 | pub EMPTY_ENUM, | |
39 | pedantic, | |
40 | "enum with no variants" | |
41 | } | |
42 | ||
43 | declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]); | |
44 | ||
45 | impl<'tcx> LateLintPass<'tcx> for EmptyEnum { | |
46 | fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { | |
47 | // Only suggest the `never_type` if the feature is enabled | |
48 | if !cx.tcx.features().never_type { | |
49 | return; | |
50 | } | |
51 | ||
52 | if let ItemKind::Enum(..) = item.kind { | |
53 | let ty = cx.tcx.type_of(item.def_id); | |
54 | let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); | |
55 | if adt.variants.is_empty() { | |
56 | span_lint_and_help( | |
57 | cx, | |
58 | EMPTY_ENUM, | |
59 | item.span, | |
60 | "enum with no variants", | |
61 | None, | |
62 | "consider using the uninhabited type `!` (never type) or a wrapper \ | |
63 | around it to introduce a type which can't be instantiated", | |
64 | ); | |
65 | } | |
66 | } | |
67 | } | |
68 | } |