Skip to content

Commit 5afa93b

Browse files
committed
Auto merge of #10481 - blyxyas:allow_attribute, r=xFrednet
Add `allow_attribute` lint Fixes #10468 changelog: new lint: [`allow_attributes`] [#10481](#10481)
2 parents c465bf7 + 1cab0cb commit 5afa93b

File tree

7 files changed

+141
-0
lines changed

7 files changed

+141
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4382,6 +4382,7 @@ Released 2018-09-13
43824382
<!-- begin autogenerated links to lint list -->
43834383
[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
43844384
[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
4385+
[`allow_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes
43854386
[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
43864387
[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
43874388
[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range

clippy_lints/src/allow_attributes.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
}

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
3535
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
3636
#[cfg(feature = "internal")]
3737
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
38+
crate::allow_attributes::ALLOW_ATTRIBUTES_INFO,
3839
crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
3940
crate::approx_const::APPROX_CONSTANT_INFO,
4041
crate::as_conversions::AS_CONVERSIONS_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ mod declared_lints;
6767
mod renamed_lints;
6868

6969
// begin lints modules, do not remove this comment, it’s used in `update_lints`
70+
mod allow_attributes;
7071
mod almost_complete_range;
7172
mod approx_const;
7273
mod as_conversions;
@@ -934,6 +935,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
934935
store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage));
935936
store.register_early_pass(|| Box::new(redundant_async_block::RedundantAsyncBlock));
936937
store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
938+
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
937939
// add lints here, do not remove this comment, it's used in `new_lint`
938940
}
939941

tests/ui/allow_attributes.fixed

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
#![warn(clippy::allow_attributes)]
4+
#![feature(lint_reasons)]
5+
6+
fn main() {}
7+
8+
// Using clippy::needless_borrow just as a placeholder, it isn't relevant.
9+
10+
// Should lint
11+
#[expect(dead_code)]
12+
struct T1;
13+
14+
struct T2; // Should not lint
15+
#[deny(clippy::needless_borrow)] // Should not lint
16+
struct T3;
17+
#[warn(clippy::needless_borrow)] // Should not lint
18+
struct T4;
19+
// `panic = "unwind"` should always be true
20+
#[cfg_attr(panic = "unwind", expect(dead_code))]
21+
struct CfgT;
22+
23+
fn ignore_inner_attr() {
24+
#![allow(unused)] // Should not lint
25+
}

tests/ui/allow_attributes.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
#![warn(clippy::allow_attributes)]
4+
#![feature(lint_reasons)]
5+
6+
fn main() {}
7+
8+
// Using clippy::needless_borrow just as a placeholder, it isn't relevant.
9+
10+
// Should lint
11+
#[allow(dead_code)]
12+
struct T1;
13+
14+
struct T2; // Should not lint
15+
#[deny(clippy::needless_borrow)] // Should not lint
16+
struct T3;
17+
#[warn(clippy::needless_borrow)] // Should not lint
18+
struct T4;
19+
// `panic = "unwind"` should always be true
20+
#[cfg_attr(panic = "unwind", allow(dead_code))]
21+
struct CfgT;
22+
23+
fn ignore_inner_attr() {
24+
#![allow(unused)] // Should not lint
25+
}

tests/ui/allow_attributes.stderr

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: #[allow] attribute found
2+
--> $DIR/allow_attributes.rs:11:3
3+
|
4+
LL | #[allow(dead_code)]
5+
| ^^^^^ help: replace it with: `expect`
6+
|
7+
= note: `-D clippy::allow-attributes` implied by `-D warnings`
8+
9+
error: #[allow] attribute found
10+
--> $DIR/allow_attributes.rs:20:30
11+
|
12+
LL | #[cfg_attr(panic = "unwind", allow(dead_code))]
13+
| ^^^^^ help: replace it with: `expect`
14+
15+
error: aborting due to 2 previous errors
16+

0 commit comments

Comments
 (0)