diff options
| author | Kalle Wachsmuth <kalle.wachsmuth@gmail.com> | 2024-09-01 19:22:35 +0200 |
|---|---|---|
| committer | Kalle Wachsmuth <kalle.wachsmuth@gmail.com> | 2025-01-26 12:18:33 +0100 |
| commit | c1dcbebd0b4f721cead9d0f7ad63b88d8effed43 (patch) | |
| tree | 6a5c390f9e0fca799549e62067161e31f9ec4e84 /compiler/rustc_lint/src/builtin.rs | |
| parent | 9e316f34720a27477c79fdb5e0193554bd4d3fb5 (diff) | |
| download | rust-c1dcbebd0b4f721cead9d0f7ad63b88d8effed43.tar.gz rust-c1dcbebd0b4f721cead9d0f7ad63b88d8effed43.zip | |
implement lint `double_negations`
Diffstat (limited to 'compiler/rustc_lint/src/builtin.rs')
| -rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 75 |
1 files changed, 64 insertions, 11 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3da9ef3ff7c..c03de687a33 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -49,16 +49,16 @@ use rustc_trait_selection::traits::{self}; use crate::errors::BuiltinEllipsisInclusiveRangePatterns; use crate::lints::{ BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink, - BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr, - BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, - BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, - BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, - BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes, - BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, - BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, - BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, - BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, InvalidAsmLabel, + BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr, BuiltinDoubleNegations, + BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint, + BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, + BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, + BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, + BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, + BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds, + BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, + BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, + BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel, }; use crate::nonstandard_style::{MethodLateContext, method_context}; use crate::{ @@ -1568,6 +1568,58 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { } } +declare_lint! { + /// The `double_negations` lint detects expressions of the form `--x`. + /// + /// ### Example + /// + /// ```rust + /// fn main() { + /// let x = 1; + /// let _b = --x; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Negating something twice is usually the same as not negating it at all. + /// However, a double negation in Rust can easily be confused with the + /// prefix decrement operator that exists in many languages derived from C. + /// Use `-(-x)` if you really wanted to negate the value twice. + /// + /// To decrement a value, use `x -= 1` instead. + pub DOUBLE_NEGATIONS, + Warn, + "detects expressions of the form `--x`" +} + +declare_lint_pass!( + /// Lint for expressions of the form `--x` that can be confused with C's + /// prefix decrement operator. + DoubleNegations => [DOUBLE_NEGATIONS] +); + +impl EarlyLintPass for DoubleNegations { + #[inline] + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { + // only lint on the innermost `--` in a chain of `-` operators, + // even if there are 3 or more negations + if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind + && let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind + && !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _)) + { + cx.emit_span_lint(DOUBLE_NEGATIONS, expr.span, BuiltinDoubleNegations { + add_parens: BuiltinDoubleNegationsAddParens { + start_span: inner.span.shrink_to_lo(), + end_span: inner.span.shrink_to_hi(), + }, + }); + } + } +} + declare_lint_pass!( /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. @@ -1586,7 +1638,8 @@ declare_lint_pass!( UNSTABLE_FEATURES, UNREACHABLE_PUB, TYPE_ALIAS_BOUNDS, - TRIVIAL_BOUNDS + TRIVIAL_BOUNDS, + DOUBLE_NEGATIONS ] ); |
