@@ -58,6 +58,7 @@ use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
5858use  crate :: lints:: { 
5959    BuiltinAnonymousParams ,  BuiltinConstNoMangle ,  BuiltinDeprecatedAttrLink , 
6060    BuiltinDeprecatedAttrLinkSuggestion ,  BuiltinDeprecatedAttrUsed ,  BuiltinDerefNullptr , 
61+     BuiltinDoubleNegations ,  BuiltinDoubleNegationsAddParens , 
6162    BuiltinEllipsisInclusiveRangePatternsLint ,  BuiltinExplicitOutlives , 
6263    BuiltinExplicitOutlivesSuggestion ,  BuiltinFeatureIssueNote ,  BuiltinIncompleteFeatures , 
6364    BuiltinIncompleteFeaturesHelp ,  BuiltinInternalFeatures ,  BuiltinKeywordIdents , 
@@ -1590,6 +1591,62 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
15901591    } 
15911592} 
15921593
1594+ declare_lint !  { 
1595+     /// The `double_negations` lint detects expressions of the form `--x`. 
1596+ /// 
1597+ /// ### Example 
1598+ /// 
1599+ /// ```rust 
1600+ /// fn main() { 
1601+ ///     let x = 1; 
1602+ ///     let _b = --x; 
1603+ /// } 
1604+ /// ``` 
1605+ /// 
1606+ /// {{produces}} 
1607+ /// 
1608+ /// ### Explanation 
1609+ /// 
1610+ /// Negating something twice is usually the same as not negating it at all. 
1611+ /// However, a double negation in Rust can easily be confused with the 
1612+ /// prefix decrement operator that exists in many languages derived from C. 
1613+ /// Use `-(-x)` if you really wanted to negate the value twice. 
1614+ /// 
1615+ /// To decrement a value, use `x -= 1` instead. 
1616+ pub  DOUBLE_NEGATIONS , 
1617+     Warn , 
1618+     "detects expressions of the form `--x`" 
1619+ } 
1620+ 
1621+ declare_lint_pass ! ( 
1622+     /// Lint for expressions of the form `--x` that can be confused with C's 
1623+ /// prefix decrement operator. 
1624+ DoubleNegations  => [ DOUBLE_NEGATIONS ] 
1625+ ) ; 
1626+ 
1627+ impl  EarlyLintPass  for  DoubleNegations  { 
1628+     #[ inline]  
1629+     fn  check_expr ( & mut  self ,  cx :  & EarlyContext < ' _ > ,  expr :  & ast:: Expr )  { 
1630+         // only lint on the innermost `--` in a chain of `-` operators, 
1631+         // even if there are 3 or more negations 
1632+         if  let  ExprKind :: Unary ( UnOp :: Neg ,  ref  inner)  = expr. kind 
1633+             && let  ExprKind :: Unary ( UnOp :: Neg ,  ref  inner2)  = inner. kind 
1634+             && !matches ! ( inner2. kind,  ExprKind :: Unary ( UnOp :: Neg ,  _) ) 
1635+         { 
1636+             cx. emit_span_lint ( 
1637+                 DOUBLE_NEGATIONS , 
1638+                 expr. span , 
1639+                 BuiltinDoubleNegations  { 
1640+                     add_parens :  BuiltinDoubleNegationsAddParens  { 
1641+                         start_span :  inner. span . shrink_to_lo ( ) , 
1642+                         end_span :  inner. span . shrink_to_hi ( ) , 
1643+                     } , 
1644+                 } , 
1645+             ) ; 
1646+         } 
1647+     } 
1648+ } 
1649+ 
15931650declare_lint_pass ! ( 
15941651    /// Does nothing as a lint pass, but registers some `Lint`s 
15951652/// which are used by other parts of the compiler. 
@@ -1608,7 +1665,8 @@ declare_lint_pass!(
16081665        UNSTABLE_FEATURES , 
16091666        UNREACHABLE_PUB , 
16101667        TYPE_ALIAS_BOUNDS , 
1611-         TRIVIAL_BOUNDS 
1668+         TRIVIAL_BOUNDS , 
1669+         DOUBLE_NEGATIONS 
16121670    ] 
16131671) ; 
16141672
0 commit comments