diff --git a/CHANGELOG.md b/CHANGELOG.md index 7acf9bc1eaa8c..14c1b0e4d3f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -616,6 +616,7 @@ All notable changes to this project will be documented in this file. [`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask diff --git a/README.md b/README.md index 24a57450b8569..6473b8efc5480 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 292 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs new file mode 100644 index 0000000000000..a148cb1c3a6f2 --- /dev/null +++ b/clippy_lints/src/assertions_on_constants.rs @@ -0,0 +1,78 @@ +use crate::consts::{constant, Constant}; +use crate::rustc::hir::{Expr, ExprKind}; +use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; +use crate::syntax::ast::LitKind; +use crate::utils::{is_direct_expn_of, span_help_and_lint}; +use if_chain::if_chain; + +/// **What it does:** Check to call assert!(true/false) +/// +/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a +/// panic!() or unreachable!() +/// +/// **Known problems:** None +/// +/// **Example:** +/// ```rust +/// assert!(false) +/// // or +/// assert!(true) +/// // or +/// const B: bool = false; +/// assert!(B) +/// ``` +declare_clippy_lint! { + pub ASSERTIONS_ON_CONSTANTS, + style, + "assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()" +} + +pub struct AssertionsOnConstants; + +impl LintPass for AssertionsOnConstants { + fn get_lints(&self) -> LintArray { + lint_array![ASSERTIONS_ON_CONSTANTS] + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { + if_chain! { + if is_direct_expn_of(e.span, "assert").is_some(); + if let ExprKind::Unary(_, ref lit) = e.node; + then { + if let ExprKind::Lit(ref inner) = lit.node { + match inner.node { + LitKind::Bool(true) => { + span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(true) will be optimized out by the compiler", + "remove it"); + }, + LitKind::Bool(false) => { + span_help_and_lint( + cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(false) should probably be replaced", + "use panic!() or unreachable!()"); + }, + _ => (), + } + } else if let Some(bool_const) = constant(cx, cx.tables, lit) { + match bool_const.0 { + Constant::Bool(true) => { + span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(const: true) will be optimized out by the compiler", + "remove it"); + }, + Constant::Bool(false) => { + span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span, + "assert!(const: false) should probably be replaced", + "use panic!() or unreachable!()"); + }, + _ => (), + } + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 608094c833d76..9d77c3c64a2ab 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -78,6 +78,7 @@ mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; pub mod arithmetic; +pub mod assertions_on_constants; pub mod assign_ops; pub mod attrs; pub mod bit_mask; @@ -477,6 +478,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box redundant_clone::RedundantClone); reg.register_late_lint_pass(box slow_vector_initialization::Pass); reg.register_late_lint_pass(box types::RefToMut); + reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -554,6 +556,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::all", Some("clippy"), vec![ approx_const::APPROX_CONSTANT, + assertions_on_constants::ASSERTIONS_ON_CONSTANTS, assign_ops::ASSIGN_OP_PATTERN, assign_ops::MISREFACTORED_ASSIGN_OP, attrs::DEPRECATED_CFG_ATTR, @@ -776,6 +779,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { ]); reg.register_lint_group("clippy::style", Some("clippy_style"), vec![ + assertions_on_constants::ASSERTIONS_ON_CONSTANTS, assign_ops::ASSIGN_OP_PATTERN, attrs::UNKNOWN_CLIPPY_LINTS, bit_mask::VERBOSE_BIT_MASK, diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index 558e001d3d10b..bd0cee7564442 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -1,3 +1,5 @@ +#![allow(clippy::assertions_on_constants)] + use std::fs::{self, DirEntry}; use std::path::Path; diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs new file mode 100644 index 0000000000000..daeceebd3a2c7 --- /dev/null +++ b/tests/ui/assertions_on_constants.rs @@ -0,0 +1,12 @@ +fn main() { + assert!(true); + assert!(false); + assert!(true, "true message"); + assert!(false, "false message"); + + const B: bool = true; + assert!(B); + + const C: bool = false; + assert!(C); +} diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr new file mode 100644 index 0000000000000..e8001acceb1ec --- /dev/null +++ b/tests/ui/assertions_on_constants.stderr @@ -0,0 +1,51 @@ +error: assert!(true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:2:5 + | +LL | assert!(true); + | ^^^^^^^^^^^^^^ + | + = note: `-D clippy::assertions-on-constants` implied by `-D warnings` + = help: remove it + +error: assert!(false) should probably be replaced + --> $DIR/assertions_on_constants.rs:3:5 + | +LL | assert!(false); + | ^^^^^^^^^^^^^^^ + | + = help: use panic!() or unreachable!() + +error: assert!(true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:4:5 + | +LL | assert!(true, "true message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: remove it + +error: assert!(false) should probably be replaced + --> $DIR/assertions_on_constants.rs:5:5 + | +LL | assert!(false, "false message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use panic!() or unreachable!() + +error: assert!(const: true) will be optimized out by the compiler + --> $DIR/assertions_on_constants.rs:8:5 + | +LL | assert!(B); + | ^^^^^^^^^^^ + | + = help: remove it + +error: assert!(const: false) should probably be replaced + --> $DIR/assertions_on_constants.rs:11:5 + | +LL | assert!(C); + | ^^^^^^^^^^^ + | + = help: use panic!() or unreachable!() + +error: aborting due to 6 previous errors + diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index 4dbb5c67f5d1d..91b65a43be77f 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -1,5 +1,5 @@ #![warn(clippy::inline_always, clippy::deprecated_semver)] - +#![allow(clippy::assertions_on_constants)] #[inline(always)] fn test_attr_lint() { assert!(true) diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 2c6dd95a63799..3c7de56406eee 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cyclomatic_complexity)] +#![allow(clippy::cyclomatic_complexity, clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index f482d7704def9..e46d753757741 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cyclomatic_complexity)] +#![allow(clippy::cyclomatic_complexity, clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 1e067a5423267..b43dc20082523 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,5 +1,5 @@ #![warn(clippy::empty_line_after_outer_attr)] - +#![allow(clippy::assertions_on_constants)] // This should produce a warning #[crate_type = "lib"] diff --git a/tests/ui/panic_unimplemented.rs b/tests/ui/panic_unimplemented.rs index f205e07cd30d9..92290da8a6ac0 100644 --- a/tests/ui/panic_unimplemented.rs +++ b/tests/ui/panic_unimplemented.rs @@ -1,5 +1,5 @@ #![warn(clippy::panic_params, clippy::unimplemented)] - +#![allow(clippy::assertions_on_constants)] fn missing() { if true { panic!("{}");