Skip to content

Commit 1ddeaa6

Browse files
committed
Auto merge of #6990 - Y-Nak:refactor-functions, r=giraffate
Organize functions into functions module Ref: #6680 Rearrange lints in `functions`. changelog: none
2 parents a521445 + 541c8b8 commit 1ddeaa6

File tree

8 files changed

+874
-741
lines changed

8 files changed

+874
-741
lines changed

clippy_lints/src/functions.rs

-738
This file was deleted.

clippy_lints/src/functions/mod.rs

+267
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
mod must_use;
2+
mod not_unsafe_ptr_arg_deref;
3+
mod result_unit_err;
4+
mod too_many_arguments;
5+
mod too_many_lines;
6+
7+
use rustc_hir as hir;
8+
use rustc_hir::intravisit;
9+
use rustc_lint::{LateContext, LateLintPass};
10+
use rustc_session::{declare_tool_lint, impl_lint_pass};
11+
use rustc_span::Span;
12+
13+
declare_clippy_lint! {
14+
/// **What it does:** Checks for functions with too many parameters.
15+
///
16+
/// **Why is this bad?** Functions with lots of parameters are considered bad
17+
/// style and reduce readability (“what does the 5th parameter mean?”). Consider
18+
/// grouping some parameters into a new type.
19+
///
20+
/// **Known problems:** None.
21+
///
22+
/// **Example:**
23+
/// ```rust
24+
/// # struct Color;
25+
/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
26+
/// // ..
27+
/// }
28+
/// ```
29+
pub TOO_MANY_ARGUMENTS,
30+
complexity,
31+
"functions with too many arguments"
32+
}
33+
34+
declare_clippy_lint! {
35+
/// **What it does:** Checks for functions with a large amount of lines.
36+
///
37+
/// **Why is this bad?** Functions with a lot of lines are harder to understand
38+
/// due to having to look at a larger amount of code to understand what the
39+
/// function is doing. Consider splitting the body of the function into
40+
/// multiple functions.
41+
///
42+
/// **Known problems:** None.
43+
///
44+
/// **Example:**
45+
/// ```rust
46+
/// fn im_too_long() {
47+
/// println!("");
48+
/// // ... 100 more LoC
49+
/// println!("");
50+
/// }
51+
/// ```
52+
pub TOO_MANY_LINES,
53+
pedantic,
54+
"functions with too many lines"
55+
}
56+
57+
declare_clippy_lint! {
58+
/// **What it does:** Checks for public functions that dereference raw pointer
59+
/// arguments but are not marked `unsafe`.
60+
///
61+
/// **Why is this bad?** The function should probably be marked `unsafe`, since
62+
/// for an arbitrary raw pointer, there is no way of telling for sure if it is
63+
/// valid.
64+
///
65+
/// **Known problems:**
66+
///
67+
/// * It does not check functions recursively so if the pointer is passed to a
68+
/// private non-`unsafe` function which does the dereferencing, the lint won't
69+
/// trigger.
70+
/// * It only checks for arguments whose type are raw pointers, not raw pointers
71+
/// got from an argument in some other way (`fn foo(bar: &[*const u8])` or
72+
/// `some_argument.get_raw_ptr()`).
73+
///
74+
/// **Example:**
75+
/// ```rust,ignore
76+
/// // Bad
77+
/// pub fn foo(x: *const u8) {
78+
/// println!("{}", unsafe { *x });
79+
/// }
80+
///
81+
/// // Good
82+
/// pub unsafe fn foo(x: *const u8) {
83+
/// println!("{}", unsafe { *x });
84+
/// }
85+
/// ```
86+
pub NOT_UNSAFE_PTR_ARG_DEREF,
87+
correctness,
88+
"public functions dereferencing raw pointer arguments but not marked `unsafe`"
89+
}
90+
91+
declare_clippy_lint! {
92+
/// **What it does:** Checks for a [`#[must_use]`] attribute on
93+
/// unit-returning functions and methods.
94+
///
95+
/// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
96+
///
97+
/// **Why is this bad?** Unit values are useless. The attribute is likely
98+
/// a remnant of a refactoring that removed the return type.
99+
///
100+
/// **Known problems:** None.
101+
///
102+
/// **Examples:**
103+
/// ```rust
104+
/// #[must_use]
105+
/// fn useless() { }
106+
/// ```
107+
pub MUST_USE_UNIT,
108+
style,
109+
"`#[must_use]` attribute on a unit-returning function / method"
110+
}
111+
112+
declare_clippy_lint! {
113+
/// **What it does:** Checks for a [`#[must_use]`] attribute without
114+
/// further information on functions and methods that return a type already
115+
/// marked as `#[must_use]`.
116+
///
117+
/// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
118+
///
119+
/// **Why is this bad?** The attribute isn't needed. Not using the result
120+
/// will already be reported. Alternatively, one can add some text to the
121+
/// attribute to improve the lint message.
122+
///
123+
/// **Known problems:** None.
124+
///
125+
/// **Examples:**
126+
/// ```rust
127+
/// #[must_use]
128+
/// fn double_must_use() -> Result<(), ()> {
129+
/// unimplemented!();
130+
/// }
131+
/// ```
132+
pub DOUBLE_MUST_USE,
133+
style,
134+
"`#[must_use]` attribute on a `#[must_use]`-returning function / method"
135+
}
136+
137+
declare_clippy_lint! {
138+
/// **What it does:** Checks for public functions that have no
139+
/// [`#[must_use]`] attribute, but return something not already marked
140+
/// must-use, have no mutable arg and mutate no statics.
141+
///
142+
/// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
143+
///
144+
/// **Why is this bad?** Not bad at all, this lint just shows places where
145+
/// you could add the attribute.
146+
///
147+
/// **Known problems:** The lint only checks the arguments for mutable
148+
/// types without looking if they are actually changed. On the other hand,
149+
/// it also ignores a broad range of potentially interesting side effects,
150+
/// because we cannot decide whether the programmer intends the function to
151+
/// be called for the side effect or the result. Expect many false
152+
/// positives. At least we don't lint if the result type is unit or already
153+
/// `#[must_use]`.
154+
///
155+
/// **Examples:**
156+
/// ```rust
157+
/// // this could be annotated with `#[must_use]`.
158+
/// fn id<T>(t: T) -> T { t }
159+
/// ```
160+
pub MUST_USE_CANDIDATE,
161+
pedantic,
162+
"function or method that could take a `#[must_use]` attribute"
163+
}
164+
165+
declare_clippy_lint! {
166+
/// **What it does:** Checks for public functions that return a `Result`
167+
/// with an `Err` type of `()`. It suggests using a custom type that
168+
/// implements `std::error::Error`.
169+
///
170+
/// **Why is this bad?** Unit does not implement `Error` and carries no
171+
/// further information about what went wrong.
172+
///
173+
/// **Known problems:** Of course, this lint assumes that `Result` is used
174+
/// for a fallible operation (which is after all the intended use). However
175+
/// code may opt to (mis)use it as a basic two-variant-enum. In that case,
176+
/// the suggestion is misguided, and the code should use a custom enum
177+
/// instead.
178+
///
179+
/// **Examples:**
180+
/// ```rust
181+
/// pub fn read_u8() -> Result<u8, ()> { Err(()) }
182+
/// ```
183+
/// should become
184+
/// ```rust,should_panic
185+
/// use std::fmt;
186+
///
187+
/// #[derive(Debug)]
188+
/// pub struct EndOfStream;
189+
///
190+
/// impl fmt::Display for EndOfStream {
191+
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192+
/// write!(f, "End of Stream")
193+
/// }
194+
/// }
195+
///
196+
/// impl std::error::Error for EndOfStream { }
197+
///
198+
/// pub fn read_u8() -> Result<u8, EndOfStream> { Err(EndOfStream) }
199+
///# fn main() {
200+
///# read_u8().unwrap();
201+
///# }
202+
/// ```
203+
///
204+
/// Note that there are crates that simplify creating the error type, e.g.
205+
/// [`thiserror`](https://docs.rs/thiserror).
206+
pub RESULT_UNIT_ERR,
207+
style,
208+
"public function returning `Result` with an `Err` type of `()`"
209+
}
210+
211+
#[derive(Copy, Clone)]
212+
pub struct Functions {
213+
too_many_arguments_threshold: u64,
214+
too_many_lines_threshold: u64,
215+
}
216+
217+
impl Functions {
218+
pub fn new(too_many_arguments_threshold: u64, too_many_lines_threshold: u64) -> Self {
219+
Self {
220+
too_many_arguments_threshold,
221+
too_many_lines_threshold,
222+
}
223+
}
224+
}
225+
226+
impl_lint_pass!(Functions => [
227+
TOO_MANY_ARGUMENTS,
228+
TOO_MANY_LINES,
229+
NOT_UNSAFE_PTR_ARG_DEREF,
230+
MUST_USE_UNIT,
231+
DOUBLE_MUST_USE,
232+
MUST_USE_CANDIDATE,
233+
RESULT_UNIT_ERR,
234+
]);
235+
236+
impl<'tcx> LateLintPass<'tcx> for Functions {
237+
fn check_fn(
238+
&mut self,
239+
cx: &LateContext<'tcx>,
240+
kind: intravisit::FnKind<'tcx>,
241+
decl: &'tcx hir::FnDecl<'_>,
242+
body: &'tcx hir::Body<'_>,
243+
span: Span,
244+
hir_id: hir::HirId,
245+
) {
246+
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
247+
too_many_lines::check_fn(cx, span, body, self.too_many_lines_threshold);
248+
not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
249+
}
250+
251+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
252+
must_use::check_item(cx, item);
253+
result_unit_err::check_item(cx, item);
254+
}
255+
256+
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
257+
must_use::check_impl_item(cx, item);
258+
result_unit_err::check_impl_item(cx, item);
259+
}
260+
261+
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
262+
too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
263+
not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
264+
must_use::check_trait_item(cx, item);
265+
result_unit_err::check_trait_item(cx, item);
266+
}
267+
}

0 commit comments

Comments
 (0)