2023-07-02 07:35:19 -05:00
|
|
|
use ast::{AttrStyle, Attribute};
|
2023-07-17 03:19:29 -05:00
|
|
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
|
|
|
use clippy_utils::is_from_proc_macro;
|
2023-03-24 08:04:35 -05:00
|
|
|
use rustc_ast as ast;
|
|
|
|
use rustc_errors::Applicability;
|
2023-05-05 10:45:49 -05:00
|
|
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
|
|
|
use rustc_middle::lint::in_external_macro;
|
2023-12-01 11:21:58 -06:00
|
|
|
use rustc_session::declare_lint_pass;
|
2023-03-24 08:04:35 -05:00
|
|
|
|
|
|
|
declare_clippy_lint! {
|
2023-10-06 10:35:45 -05:00
|
|
|
/// ### What it does
|
2023-04-23 06:03:09 -05:00
|
|
|
/// Checks for usage of the `#[allow]` attribute and suggests replacing it with
|
2023-03-24 08:04:35 -05:00
|
|
|
/// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
|
|
|
|
///
|
|
|
|
/// The expect attribute is still unstable and requires the `lint_reasons`
|
|
|
|
/// on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to
|
|
|
|
/// the crate root.
|
|
|
|
///
|
|
|
|
/// This lint only warns outer attributes (`#[allow]`), as inner attributes
|
|
|
|
/// (`#![allow]`) are usually used to enable or disable lints on a global scale.
|
|
|
|
///
|
|
|
|
/// ### Why is this bad?
|
|
|
|
/// `#[expect]` attributes suppress the lint emission, but emit a warning, if
|
|
|
|
/// the expectation is unfulfilled. This can be useful to be notified when the
|
|
|
|
/// lint is no longer triggered.
|
|
|
|
///
|
|
|
|
/// ### Example
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// #[allow(unused_mut)]
|
|
|
|
/// fn foo() -> usize {
|
|
|
|
/// let mut a = Vec::new();
|
|
|
|
/// a.len()
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
/// Use instead:
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// #![feature(lint_reasons)]
|
|
|
|
/// #[expect(unused_mut)]
|
|
|
|
/// fn foo() -> usize {
|
|
|
|
/// let mut a = Vec::new();
|
|
|
|
/// a.len()
|
|
|
|
/// }
|
|
|
|
/// ```
|
2023-06-02 04:41:57 -05:00
|
|
|
#[clippy::version = "1.70.0"]
|
2023-03-24 08:04:35 -05:00
|
|
|
pub ALLOW_ATTRIBUTES,
|
|
|
|
restriction,
|
|
|
|
"`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings."
|
|
|
|
}
|
|
|
|
|
|
|
|
declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]);
|
|
|
|
|
|
|
|
impl LateLintPass<'_> for AllowAttribute {
|
|
|
|
// Separate each crate's features.
|
2023-07-02 07:35:19 -05:00
|
|
|
fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) {
|
2023-11-16 12:13:24 -06:00
|
|
|
if !in_external_macro(cx.sess(), attr.span)
|
|
|
|
&& cx.tcx.features().lint_reasons
|
|
|
|
&& let AttrStyle::Outer = attr.style
|
|
|
|
&& let Some(ident) = attr.ident()
|
|
|
|
&& ident.name == rustc_span::symbol::sym::allow
|
|
|
|
&& !is_from_proc_macro(cx, &attr)
|
|
|
|
{
|
|
|
|
span_lint_and_sugg(
|
|
|
|
cx,
|
|
|
|
ALLOW_ATTRIBUTES,
|
|
|
|
ident.span,
|
|
|
|
"#[allow] attribute found",
|
|
|
|
"replace it with",
|
|
|
|
"expect".into(),
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
2023-03-24 08:04:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|