Skip to content

Commit 1b4c281

Browse files
committed
RFC 2383: Stabilize lint_reasons in Clippy 🖇️
1 parent dfaa53f commit 1b4c281

File tree

74 files changed

+611
-573
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+611
-573
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,7 @@ Released 2022-05-19
19431943
[#8218](https://github.com/rust-lang/rust-clippy/pull/8218)
19441944
* [`needless_match`]
19451945
[#8471](https://github.com/rust-lang/rust-clippy/pull/8471)
1946-
* [`allow_attributes_without_reason`] (Requires `#![feature(lint_reasons)]`)
1946+
* [`allow_attributes_without_reason`]
19471947
[#8504](https://github.com/rust-lang/rust-clippy/pull/8504)
19481948
* [`print_in_format_impl`]
19491949
[#8253](https://github.com/rust-lang/rust-clippy/pull/8253)

book/src/lint_configuration.md

+2
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,8 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
669669

670670
---
671671
**Affected lints:**
672+
* [`allow_attributes`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes)
673+
* [`allow_attributes_without_reason`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason)
672674
* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
673675
* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
674676
* [`assigning_clones`](https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones)

clippy_config/src/conf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ define_Conf! {
265265
///
266266
/// Suppress lints whenever the suggested change would cause breakage for other crates.
267267
(avoid_breaking_exported_api: bool = true),
268-
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS.
268+
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON.
269269
///
270270
/// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
271271
#[default_text = ""]

clippy_config/src/msrvs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ macro_rules! msrv_aliases {
1717

1818
// names may refer to stabilized feature flags or library items
1919
msrv_aliases! {
20+
1,81,0 { LINT_REASONS_STABILIZATION }
2021
1,77,0 { C_STR_LITERALS }
2122
1,76,0 { PTR_FROM_REF }
2223
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }

clippy_lints/src/allow_attributes.rs

-74
This file was deleted.
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::is_from_proc_macro;
3+
use rustc_ast::{AttrStyle, Attribute};
4+
use rustc_errors::Applicability;
5+
use rustc_lint::{LateContext, LintContext};
6+
use rustc_middle::lint::in_external_macro;
7+
use super::ALLOW_ATTRIBUTES;
8+
9+
// Separate each crate's features.
10+
pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
11+
if !in_external_macro(cx.sess(), attr.span)
12+
&& let AttrStyle::Outer = attr.style
13+
&& let Some(ident) = attr.ident()
14+
&& !is_from_proc_macro(cx, &attr)
15+
{
16+
span_lint_and_sugg(
17+
cx,
18+
ALLOW_ATTRIBUTES,
19+
ident.span,
20+
"#[allow] attribute found",
21+
"replace it with",
22+
"expect".into(),
23+
Applicability::MachineApplicable,
24+
);
25+
}
26+
}

clippy_lints/src/attrs/allow_attributes_without_reason.rs

-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ use rustc_span::sym;
88
use rustc_span::symbol::Symbol;
99

1010
pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) {
11-
// Check for the feature
12-
if !cx.tcx.features().lint_reasons {
13-
return;
14-
}
15-
1611
// Check if the reason is present
1712
if let Some(item) = items.last().and_then(NestedMetaItem::meta_item)
1813
&& let MetaItemKind::NameValue(_) = &item.kind

clippy_lints/src/attrs/mod.rs

+61-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! checks for attributes
22
33
mod allow_attributes_without_reason;
4+
mod allow_attributes;
45
mod blanket_clippy_restriction_lints;
56
mod deprecated_cfg_attr;
67
mod deprecated_semver;
@@ -14,11 +15,11 @@ mod unnecessary_clippy_cfg;
1415
mod useless_attribute;
1516
mod utils;
1617

17-
use clippy_config::msrvs::Msrv;
18+
use clippy_config::msrvs::{self, Msrv};
1819
use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
1920
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
2021
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
21-
use rustc_session::{declare_lint_pass, impl_lint_pass};
22+
use rustc_session::impl_lint_pass;
2223
use rustc_span::sym;
2324
use utils::{is_lint_level, is_relevant_impl, is_relevant_item, is_relevant_trait};
2425

@@ -272,23 +273,17 @@ declare_clippy_lint! {
272273
/// ### What it does
273274
/// Checks for attributes that allow lints without a reason.
274275
///
275-
/// (This requires the `lint_reasons` feature)
276-
///
277276
/// ### Why restrict this?
278277
/// Justifying each `allow` helps readers understand the reasoning,
279278
/// and may allow removing `allow` attributes if their purpose is obsolete.
280279
///
281280
/// ### Example
282281
/// ```no_run
283-
/// #![feature(lint_reasons)]
284-
///
285282
/// #![allow(clippy::some_lint)]
286283
/// ```
287284
///
288285
/// Use instead:
289286
/// ```no_run
290-
/// #![feature(lint_reasons)]
291-
///
292287
/// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")]
293288
/// ```
294289
#[clippy::version = "1.61.0"]
@@ -297,6 +292,41 @@ declare_clippy_lint! {
297292
"ensures that all `allow` and `expect` attributes have a reason"
298293
}
299294

295+
declare_clippy_lint! {
296+
/// ### What it does
297+
/// Checks for usage of the `#[allow]` attribute and suggests replacing it with
298+
/// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
299+
///
300+
/// This lint only warns outer attributes (`#[allow]`), as inner attributes
301+
/// (`#![allow]`) are usually used to enable or disable lints on a global scale.
302+
///
303+
/// ### Why is this bad?
304+
/// `#[expect]` attributes suppress the lint emission, but emit a warning, if
305+
/// the expectation is unfulfilled. This can be useful to be notified when the
306+
/// lint is no longer triggered.
307+
///
308+
/// ### Example
309+
/// ```rust,ignore
310+
/// #[allow(unused_mut)]
311+
/// fn foo() -> usize {
312+
/// let mut a = Vec::new();
313+
/// a.len()
314+
/// }
315+
/// ```
316+
/// Use instead:
317+
/// ```rust,ignore
318+
/// #[expect(unused_mut)]
319+
/// fn foo() -> usize {
320+
/// let mut a = Vec::new();
321+
/// a.len()
322+
/// }
323+
/// ```
324+
#[clippy::version = "1.70.0"]
325+
pub ALLOW_ATTRIBUTES,
326+
restriction,
327+
"`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings."
328+
}
329+
300330
declare_clippy_lint! {
301331
/// ### What it does
302332
/// Checks for `#[should_panic]` attributes without specifying the expected panic message.
@@ -469,7 +499,12 @@ declare_clippy_lint! {
469499
"duplicated attribute"
470500
}
471501

472-
declare_lint_pass!(Attributes => [
502+
#[derive(Clone)]
503+
pub struct Attributes {
504+
msrv: Msrv,
505+
}
506+
507+
impl_lint_pass!(Attributes => [
473508
ALLOW_ATTRIBUTES_WITHOUT_REASON,
474509
INLINE_ALWAYS,
475510
DEPRECATED_SEMVER,
@@ -480,6 +515,13 @@ declare_lint_pass!(Attributes => [
480515
DUPLICATED_ATTRIBUTES,
481516
]);
482517

518+
impl Attributes {
519+
#[must_use]
520+
pub fn new(msrv: Msrv) -> Self {
521+
Self { msrv }
522+
}
523+
}
524+
483525
impl<'tcx> LateLintPass<'tcx> for Attributes {
484526
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
485527
blanket_clippy_restriction_lints::check_command_line(cx);
@@ -492,8 +534,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
492534
if is_lint_level(ident.name, attr.id) {
493535
blanket_clippy_restriction_lints::check(cx, ident.name, items);
494536
}
537+
if matches!(ident.name, sym::allow) {
538+
if self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
539+
allow_attributes::check(cx, attr);
540+
}
541+
}
495542
if matches!(ident.name, sym::allow | sym::expect) {
496-
allow_attributes_without_reason::check(cx, ident.name, items, attr);
543+
if self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
544+
allow_attributes_without_reason::check(cx, ident.name, items, attr);
545+
}
497546
}
498547
if items.is_empty() || !attr.has_name(sym::deprecated) {
499548
return;
@@ -537,6 +586,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
537586
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
538587
}
539588
}
589+
590+
extract_msrv_attr!(LateContext);
540591
}
541592

542593
pub struct EarlyAttributes {

clippy_lints/src/declared_lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
3838
#[cfg(feature = "internal")]
3939
crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO,
4040
crate::absolute_paths::ABSOLUTE_PATHS_INFO,
41-
crate::allow_attributes::ALLOW_ATTRIBUTES_INFO,
4241
crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
4342
crate::approx_const::APPROX_CONSTANT_INFO,
4443
crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO,
@@ -49,6 +48,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
4948
crate::assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES_INFO,
5049
crate::assigning_clones::ASSIGNING_CLONES_INFO,
5150
crate::async_yields_async::ASYNC_YIELDS_ASYNC_INFO,
51+
crate::attrs::ALLOW_ATTRIBUTES_INFO,
5252
crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO,
5353
crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
5454
crate::attrs::DEPRECATED_CFG_ATTR_INFO,

clippy_lints/src/lib.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![feature(if_let_guard)]
77
#![feature(iter_intersperse)]
88
#![feature(let_chains)]
9-
#![feature(lint_reasons)]
9+
#![cfg_attr(bootstrap, feature(lint_reasons))]
1010
#![feature(never_type)]
1111
#![feature(rustc_private)]
1212
#![feature(stmt_expr_attributes)]
@@ -73,7 +73,6 @@ mod renamed_lints;
7373

7474
// begin lints modules, do not remove this comment, it’s used in `update_lints`
7575
mod absolute_paths;
76-
mod allow_attributes;
7776
mod almost_complete_range;
7877
mod approx_const;
7978
mod arc_with_non_send_sync;
@@ -699,7 +698,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
699698
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
700699
store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
701700
store.register_late_pass(|_| Box::new(len_zero::LenZero));
702-
store.register_late_pass(|_| Box::new(attrs::Attributes));
701+
store.register_late_pass(move |_| Box::new(attrs::Attributes::new(msrv())));
703702
store.register_late_pass(|_| Box::new(blocks_in_conditions::BlocksInConditions));
704703
store.register_late_pass(|_| Box::new(unicode::Unicode));
705704
store.register_late_pass(|_| Box::new(uninit_vec::UninitVec));
@@ -1065,7 +1064,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
10651064
store.register_late_pass(|_| Box::new(needless_maybe_sized::NeedlessMaybeSized));
10661065
store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock));
10671066
store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
1068-
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
10691067
store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
10701068
store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
10711069
store.register_late_pass(move |_| {

clippy_utils/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#![feature(f16)]
66
#![feature(if_let_guard)]
77
#![feature(let_chains)]
8-
#![feature(lint_reasons)]
8+
#![cfg_attr(bootstrap, feature(lint_reasons))]
99
#![feature(never_type)]
1010
#![feature(rustc_private)]
1111
#![feature(assert_matches)]

src/driver.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![allow(rustc::untranslatable_diagnostic)]
33
#![feature(rustc_private)]
44
#![feature(let_chains)]
5-
#![feature(lint_reasons)]
5+
#![cfg_attr(bootstrap, feature(lint_reasons))]
66
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
77
// warn on lints, that are included in `rust-lang/rust`s bootstrap
88
#![warn(rust_2018_idioms, unused_lifetimes)]

tests/ui-cargo/duplicate_mod/fail/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(lint_reasons)]
21

32
mod a;
43

tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error: the feature `lint_reasons` has been stable since 1.81.0-dev and no longer requires an attribute to enable
2+
--> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:2:24
3+
|
4+
LL | #![feature(decl_macro, lint_reasons)]
5+
| ^^^^^^^^^^^^
6+
|
7+
= note: `-D stable-features` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(stable_features)]`
9+
110
error: this macro expands metavariables in an unsafe block
211
--> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9
312
|
@@ -183,5 +192,5 @@ LL | | }
183192
= help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
184193
= help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
185194

186-
error: aborting due to 14 previous errors
195+
error: aborting due to 15 previous errors
187196

0 commit comments

Comments
 (0)