]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
Rollup merge of #104901 - krtab:filetype_compare, r=the8472
[rust.git] / src / tools / clippy / clippy_lints / src / partial_pub_fields.rs
1 use clippy_utils::diagnostics::span_lint_and_help;
2 use rustc_ast::ast::{Item, ItemKind};
3 use rustc_lint::{EarlyContext, EarlyLintPass};
4 use rustc_session::{declare_lint_pass, declare_tool_lint};
5
6 declare_clippy_lint! {
7     /// ### What it does
8     /// Checks whether partial fields of a struct are public.
9     ///
10     /// Either make all fields of a type public, or make none of them public
11     ///
12     /// ### Why is this bad?
13     /// Most types should either be:
14     /// * Abstract data types: complex objects with opaque implementation which guard
15     /// interior invariants and expose intentionally limited API to the outside world.
16     /// * Data: relatively simple objects which group a bunch of related attributes together.
17     ///
18     /// ### Example
19     /// ```rust
20     /// pub struct Color {
21     ///     pub r: u8,
22     ///     pub g: u8,
23     ///     b: u8,
24     /// }
25     /// ```
26     /// Use instead:
27     /// ```rust
28     /// pub struct Color {
29     ///     pub r: u8,
30     ///     pub g: u8,
31     ///     pub b: u8,
32     /// }
33     /// ```
34     #[clippy::version = "1.66.0"]
35     pub PARTIAL_PUB_FIELDS,
36     restriction,
37     "partial fields of a struct are public"
38 }
39 declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]);
40
41 impl EarlyLintPass for PartialPubFields {
42     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
43         let ItemKind::Struct(ref st, _) = item.kind else {
44             return;
45         };
46
47         let mut fields = st.fields().iter();
48         let Some(first_field) = fields.next() else {
49             // Empty struct.
50             return;
51         };
52         let all_pub = first_field.vis.kind.is_pub();
53         let all_priv = !all_pub;
54
55         let msg = "mixed usage of pub and non-pub fields";
56
57         for field in fields {
58             if all_priv && field.vis.kind.is_pub() {
59                 span_lint_and_help(
60                     cx,
61                     PARTIAL_PUB_FIELDS,
62                     field.vis.span,
63                     msg,
64                     None,
65                     "consider using private field here",
66                 );
67                 return;
68             } else if all_pub && !field.vis.kind.is_pub() {
69                 span_lint_and_help(
70                     cx,
71                     PARTIAL_PUB_FIELDS,
72                     field.vis.span,
73                     msg,
74                     None,
75                     "consider using public field here",
76                 );
77                 return;
78             }
79         }
80     }
81 }