@@ -49,16 +49,16 @@ use rustc_trait_selection::traits::{self};
4949use crate :: errors:: BuiltinEllipsisInclusiveRangePatterns ;
5050use crate :: lints:: {
5151 BuiltinAnonymousParams , BuiltinConstNoMangle , BuiltinDeprecatedAttrLink ,
52- BuiltinDeprecatedAttrLinkSuggestion , BuiltinDerefNullptr ,
53- BuiltinEllipsisInclusiveRangePatternsLint , BuiltinExplicitOutlives ,
54- BuiltinExplicitOutlivesSuggestion , BuiltinFeatureIssueNote , BuiltinIncompleteFeatures ,
55- BuiltinIncompleteFeaturesHelp , BuiltinInternalFeatures , BuiltinKeywordIdents ,
56- BuiltinMissingCopyImpl , BuiltinMissingDebugImpl , BuiltinMissingDoc , BuiltinMutablesTransmutes ,
57- BuiltinNoMangleGeneric , BuiltinNonShorthandFieldPatterns , BuiltinSpecialModuleNameUsed ,
58- BuiltinTrivialBounds , BuiltinTypeAliasBounds , BuiltinUngatedAsyncFnTrackCaller ,
59- BuiltinUnpermittedTypeInit , BuiltinUnpermittedTypeInitSub , BuiltinUnreachablePub ,
60- BuiltinUnsafe , BuiltinUnstableFeatures , BuiltinUnusedDocComment , BuiltinUnusedDocCommentSub ,
61- BuiltinWhileTrue , InvalidAsmLabel ,
52+ BuiltinDeprecatedAttrLinkSuggestion , BuiltinDerefNullptr , BuiltinDoubleNegations ,
53+ BuiltinDoubleNegationsAddParens , BuiltinEllipsisInclusiveRangePatternsLint ,
54+ BuiltinExplicitOutlives , BuiltinExplicitOutlivesSuggestion , BuiltinFeatureIssueNote ,
55+ BuiltinIncompleteFeatures , BuiltinIncompleteFeaturesHelp , BuiltinInternalFeatures ,
56+ BuiltinKeywordIdents , BuiltinMissingCopyImpl , BuiltinMissingDebugImpl , BuiltinMissingDoc ,
57+ BuiltinMutablesTransmutes , BuiltinNoMangleGeneric , BuiltinNonShorthandFieldPatterns ,
58+ BuiltinSpecialModuleNameUsed , BuiltinTrivialBounds , BuiltinTypeAliasBounds ,
59+ BuiltinUngatedAsyncFnTrackCaller , BuiltinUnpermittedTypeInit , BuiltinUnpermittedTypeInitSub ,
60+ BuiltinUnreachablePub , BuiltinUnsafe , BuiltinUnstableFeatures , BuiltinUnusedDocComment ,
61+ BuiltinUnusedDocCommentSub , BuiltinWhileTrue , InvalidAsmLabel ,
6262} ;
6363use crate :: nonstandard_style:: { MethodLateContext , method_context} ;
6464use crate :: {
@@ -1568,6 +1568,58 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
15681568 }
15691569}
15701570
1571+ declare_lint ! {
1572+ /// The `double_negations` lint detects expressions of the form `--x`.
1573+ ///
1574+ /// ### Example
1575+ ///
1576+ /// ```rust
1577+ /// fn main() {
1578+ /// let x = 1;
1579+ /// let _b = --x;
1580+ /// }
1581+ /// ```
1582+ ///
1583+ /// {{produces}}
1584+ ///
1585+ /// ### Explanation
1586+ ///
1587+ /// Negating something twice is usually the same as not negating it at all.
1588+ /// However, a double negation in Rust can easily be confused with the
1589+ /// prefix decrement operator that exists in many languages derived from C.
1590+ /// Use `-(-x)` if you really wanted to negate the value twice.
1591+ ///
1592+ /// To decrement a value, use `x -= 1` instead.
1593+ pub DOUBLE_NEGATIONS ,
1594+ Warn ,
1595+ "detects expressions of the form `--x`"
1596+ }
1597+
1598+ declare_lint_pass ! (
1599+ /// Lint for expressions of the form `--x` that can be confused with C's
1600+ /// prefix decrement operator.
1601+ DoubleNegations => [ DOUBLE_NEGATIONS ]
1602+ ) ;
1603+
1604+ impl EarlyLintPass for DoubleNegations {
1605+ #[ inline]
1606+ fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , expr : & ast:: Expr ) {
1607+ // only lint on the innermost `--` in a chain of `-` operators,
1608+ // even if there are 3 or more negations
1609+ if let ExprKind :: Unary ( UnOp :: Neg , ref inner) = expr. kind
1610+ && let ExprKind :: Unary ( UnOp :: Neg , ref inner2) = inner. kind
1611+ && !matches ! ( inner2. kind, ExprKind :: Unary ( UnOp :: Neg , _) )
1612+ {
1613+ cx. emit_span_lint ( DOUBLE_NEGATIONS , expr. span , BuiltinDoubleNegations {
1614+ add_parens : BuiltinDoubleNegationsAddParens {
1615+ start_span : inner. span . shrink_to_lo ( ) ,
1616+ end_span : inner. span . shrink_to_hi ( ) ,
1617+ } ,
1618+ } ) ;
1619+ }
1620+ }
1621+ }
1622+
15711623declare_lint_pass ! (
15721624 /// Does nothing as a lint pass, but registers some `Lint`s
15731625 /// which are used by other parts of the compiler.
@@ -1586,7 +1638,8 @@ declare_lint_pass!(
15861638 UNSTABLE_FEATURES ,
15871639 UNREACHABLE_PUB ,
15881640 TYPE_ALIAS_BOUNDS ,
1589- TRIVIAL_BOUNDS
1641+ TRIVIAL_BOUNDS ,
1642+ DOUBLE_NEGATIONS
15901643 ]
15911644) ;
15921645
0 commit comments