]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/allow_attributes.rs
15d46e954a9a59b6633d5411a584f79c7d08e950
[rustc.git] / src / tools / clippy / clippy_lints / src / allow_attributes.rs
1 use ast::AttrStyle;
2 use clippy_utils::diagnostics::span_lint_and_sugg;
3 use rustc_ast as ast;
4 use rustc_errors::Applicability;
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7
8 declare_clippy_lint! {
9 /// Detects uses of the `#[allow]` attribute and suggests replacing it with
10 /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
11 ///
12 /// The expect attribute is still unstable and requires the `lint_reasons`
13 /// on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to
14 /// the crate root.
15 ///
16 /// This lint only warns outer attributes (`#[allow]`), as inner attributes
17 /// (`#![allow]`) are usually used to enable or disable lints on a global scale.
18 ///
19 /// ### Why is this bad?
20 ///
21 /// `#[expect]` attributes suppress the lint emission, but emit a warning, if
22 /// the expectation is unfulfilled. This can be useful to be notified when the
23 /// lint is no longer triggered.
24 ///
25 /// ### Example
26 /// ```rust,ignore
27 /// #[allow(unused_mut)]
28 /// fn foo() -> usize {
29 /// let mut a = Vec::new();
30 /// a.len()
31 /// }
32 /// ```
33 /// Use instead:
34 /// ```rust,ignore
35 /// #![feature(lint_reasons)]
36 /// #[expect(unused_mut)]
37 /// fn foo() -> usize {
38 /// let mut a = Vec::new();
39 /// a.len()
40 /// }
41 /// ```
42 #[clippy::version = "1.69.0"]
43 pub ALLOW_ATTRIBUTES,
44 restriction,
45 "`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings."
46 }
47
48 declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]);
49
50 impl LateLintPass<'_> for AllowAttribute {
51 // Separate each crate's features.
52 fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
53 if_chain! {
54 if cx.tcx.features().lint_reasons;
55 if let AttrStyle::Outer = attr.style;
56 if let Some(ident) = attr.ident();
57 if ident.name == rustc_span::symbol::sym::allow;
58 then {
59 span_lint_and_sugg(
60 cx,
61 ALLOW_ATTRIBUTES,
62 ident.span,
63 "#[allow] attribute found",
64 "replace it with",
65 "expect".into(),
66 Applicability::MachineApplicable,
67 );
68 }
69 }
70 }
71 }