implement lint double_negations
This commit is contained in:
parent
9e316f3472
commit
c1dcbebd0b
8 changed files with 159 additions and 16 deletions
|
@ -76,6 +76,11 @@ lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$rea
|
||||||
lint_builtin_deref_nullptr = dereferencing a null pointer
|
lint_builtin_deref_nullptr = dereferencing a null pointer
|
||||||
.label = this code causes undefined behavior when executed
|
.label = this code causes undefined behavior when executed
|
||||||
|
|
||||||
|
lint_builtin_double_negations = use of a double negation
|
||||||
|
.note = the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
|
||||||
|
.note_decrement = use `-= 1` if you meant to decrement the value
|
||||||
|
.add_parens_suggestion = add parentheses for clarity
|
||||||
|
|
||||||
lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
|
lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
|
||||||
.suggestion = use `..=` for an inclusive range
|
.suggestion = use `..=` for an inclusive range
|
||||||
|
|
||||||
|
|
|
@ -49,16 +49,16 @@ use rustc_trait_selection::traits::{self};
|
||||||
use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
|
use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
|
||||||
use crate::lints::{
|
use crate::lints::{
|
||||||
BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
|
BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
|
||||||
BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr,
|
BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr, BuiltinDoubleNegations,
|
||||||
BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
|
BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint,
|
||||||
BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
|
BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote,
|
||||||
BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
|
BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures,
|
||||||
BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes,
|
BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
|
||||||
BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed,
|
BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
|
||||||
BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller,
|
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
|
||||||
BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub,
|
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
|
||||||
BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
|
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
|
||||||
BuiltinWhileTrue, InvalidAsmLabel,
|
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
|
||||||
};
|
};
|
||||||
use crate::nonstandard_style::{MethodLateContext, method_context};
|
use crate::nonstandard_style::{MethodLateContext, method_context};
|
||||||
use crate::{
|
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!(
|
declare_lint_pass!(
|
||||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||||
/// which are used by other parts of the compiler.
|
/// which are used by other parts of the compiler.
|
||||||
|
@ -1586,7 +1638,8 @@ declare_lint_pass!(
|
||||||
UNSTABLE_FEATURES,
|
UNSTABLE_FEATURES,
|
||||||
UNREACHABLE_PUB,
|
UNREACHABLE_PUB,
|
||||||
TYPE_ALIAS_BOUNDS,
|
TYPE_ALIAS_BOUNDS,
|
||||||
TRIVIAL_BOUNDS
|
TRIVIAL_BOUNDS,
|
||||||
|
DOUBLE_NEGATIONS
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ early_lint_methods!(
|
||||||
UnusedDocComment: UnusedDocComment,
|
UnusedDocComment: UnusedDocComment,
|
||||||
Expr2024: Expr2024,
|
Expr2024: Expr2024,
|
||||||
Precedence: Precedence,
|
Precedence: Precedence,
|
||||||
|
DoubleNegations: DoubleNegations,
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -331,6 +331,24 @@ pub(crate) struct BuiltinTrivialBounds<'a> {
|
||||||
pub predicate: Clause<'a>,
|
pub predicate: Clause<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(lint_builtin_double_negations)]
|
||||||
|
#[note(lint_note)]
|
||||||
|
#[note(lint_note_decrement)]
|
||||||
|
pub(crate) struct BuiltinDoubleNegations {
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub add_parens: BuiltinDoubleNegationsAddParens,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")]
|
||||||
|
pub(crate) struct BuiltinDoubleNegationsAddParens {
|
||||||
|
#[suggestion_part(code = "(")]
|
||||||
|
pub start_span: Span,
|
||||||
|
#[suggestion_part(code = ")")]
|
||||||
|
pub end_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
|
pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
|
||||||
#[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
|
#[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
|
||||||
|
|
9
tests/ui/lint/lint-double-negations.rs
Normal file
9
tests/ui/lint/lint-double-negations.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
//@ check-pass
|
||||||
|
fn main() {
|
||||||
|
let x = 1;
|
||||||
|
-x;
|
||||||
|
-(-x);
|
||||||
|
--x; //~ WARN use of a double negation
|
||||||
|
---x; //~ WARN use of a double negation
|
||||||
|
let _y = --(-x); //~ WARN use of a double negation
|
||||||
|
}
|
42
tests/ui/lint/lint-double-negations.stderr
Normal file
42
tests/ui/lint/lint-double-negations.stderr
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
warning: use of a double negation
|
||||||
|
--> $DIR/lint-double-negations.rs:6:5
|
||||||
|
|
|
||||||
|
LL | --x;
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
|
||||||
|
= note: use `-= 1` if you meant to decrement the value
|
||||||
|
= note: `#[warn(double_negations)]` on by default
|
||||||
|
help: add parentheses for clarity
|
||||||
|
|
|
||||||
|
LL | -(-x);
|
||||||
|
| + +
|
||||||
|
|
||||||
|
warning: use of a double negation
|
||||||
|
--> $DIR/lint-double-negations.rs:7:6
|
||||||
|
|
|
||||||
|
LL | ---x;
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
|
||||||
|
= note: use `-= 1` if you meant to decrement the value
|
||||||
|
help: add parentheses for clarity
|
||||||
|
|
|
||||||
|
LL | --(-x);
|
||||||
|
| + +
|
||||||
|
|
||||||
|
warning: use of a double negation
|
||||||
|
--> $DIR/lint-double-negations.rs:8:14
|
||||||
|
|
|
||||||
|
LL | let _y = --(-x);
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
|
||||||
|
= note: use `-= 1` if you meant to decrement the value
|
||||||
|
help: add parentheses for clarity
|
||||||
|
|
|
||||||
|
LL | let _y = -(-(-x));
|
||||||
|
| + +
|
||||||
|
|
||||||
|
warning: 3 warnings emitted
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
|
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
|
||||||
|
//~| WARN use of a double negation
|
||||||
|
|
||||||
let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
|
let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
|
||||||
let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
|
let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
warning: use of a double negation
|
||||||
|
--> $DIR/lint-type-overflow2.rs:6:18
|
||||||
|
|
|
||||||
|
LL | let x2: i8 = --128;
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
|
||||||
|
= note: use `-= 1` if you meant to decrement the value
|
||||||
|
= note: `#[warn(double_negations)]` on by default
|
||||||
|
help: add parentheses for clarity
|
||||||
|
|
|
||||||
|
LL | let x2: i8 = -(-128);
|
||||||
|
| + +
|
||||||
|
|
||||||
error: literal out of range for `i8`
|
error: literal out of range for `i8`
|
||||||
--> $DIR/lint-type-overflow2.rs:6:20
|
--> $DIR/lint-type-overflow2.rs:6:20
|
||||||
|
|
|
|
||||||
|
@ -13,7 +27,7 @@ LL | #![deny(overflowing_literals)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: literal out of range for `f32`
|
error: literal out of range for `f32`
|
||||||
--> $DIR/lint-type-overflow2.rs:8:14
|
--> $DIR/lint-type-overflow2.rs:9:14
|
||||||
|
|
|
|
||||||
LL | let x = -3.40282357e+38_f32;
|
LL | let x = -3.40282357e+38_f32;
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -21,7 +35,7 @@ LL | let x = -3.40282357e+38_f32;
|
||||||
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
|
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
|
||||||
|
|
||||||
error: literal out of range for `f32`
|
error: literal out of range for `f32`
|
||||||
--> $DIR/lint-type-overflow2.rs:9:14
|
--> $DIR/lint-type-overflow2.rs:10:14
|
||||||
|
|
|
|
||||||
LL | let x = 3.40282357e+38_f32;
|
LL | let x = 3.40282357e+38_f32;
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -29,7 +43,7 @@ LL | let x = 3.40282357e+38_f32;
|
||||||
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
|
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
|
||||||
|
|
||||||
error: literal out of range for `f64`
|
error: literal out of range for `f64`
|
||||||
--> $DIR/lint-type-overflow2.rs:10:14
|
--> $DIR/lint-type-overflow2.rs:11:14
|
||||||
|
|
|
|
||||||
LL | let x = -1.7976931348623159e+308_f64;
|
LL | let x = -1.7976931348623159e+308_f64;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -37,12 +51,12 @@ LL | let x = -1.7976931348623159e+308_f64;
|
||||||
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
|
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
|
||||||
|
|
||||||
error: literal out of range for `f64`
|
error: literal out of range for `f64`
|
||||||
--> $DIR/lint-type-overflow2.rs:11:14
|
--> $DIR/lint-type-overflow2.rs:12:14
|
||||||
|
|
|
|
||||||
LL | let x = 1.7976931348623159e+308_f64;
|
LL | let x = 1.7976931348623159e+308_f64;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
|
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue