Skip to content

Commit 09397d9

Browse files
committed
Auto merge of #3686 - flip1995:rollup, r=flip1995
Rollup of 4 pull requests Successful merges: - #3582 (Add assert(true) and assert(false) lints) - #3679 (Fix automatic suggestion on `use_self`.) - #3684 ("make_return" and "blockify" convenience methods, fixes #3683) - #3685 (Rustup) Failed merges: r? @ghost
2 parents 9d5b148 + bd6e510 commit 09397d9

17 files changed

+599
-47
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ All notable changes to this project will be documented in this file.
616616
[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
617617
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
618618
[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
619+
[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants
619620
[`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern
620621
[`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops
621622
[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
99

10-
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
10+
[There are 292 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1111

1212
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1313

clippy_lints/src/arithmetic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
128128
}
129129
self.const_span = Some(body_span);
130130
},
131-
hir::BodyOwnerKind::Fn => (),
131+
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (),
132132
}
133133
}
134134

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
use crate::consts::{constant, Constant};
11+
use crate::rustc::hir::{Expr, ExprKind};
12+
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
13+
use crate::rustc::{declare_tool_lint, lint_array};
14+
use crate::syntax::ast::LitKind;
15+
use crate::utils::{is_direct_expn_of, span_help_and_lint};
16+
use if_chain::if_chain;
17+
18+
/// **What it does:** Check to call assert!(true/false)
19+
///
20+
/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
21+
/// panic!() or unreachable!()
22+
///
23+
/// **Known problems:** None
24+
///
25+
/// **Example:**
26+
/// ```rust
27+
/// assert!(false)
28+
/// // or
29+
/// assert!(true)
30+
/// // or
31+
/// const B: bool = false;
32+
/// assert!(B)
33+
/// ```
34+
declare_clippy_lint! {
35+
pub ASSERTIONS_ON_CONSTANTS,
36+
style,
37+
"assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()"
38+
}
39+
40+
pub struct AssertionsOnConstants;
41+
42+
impl LintPass for AssertionsOnConstants {
43+
fn get_lints(&self) -> LintArray {
44+
lint_array![ASSERTIONS_ON_CONSTANTS]
45+
}
46+
}
47+
48+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
49+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
50+
if_chain! {
51+
if is_direct_expn_of(e.span, "assert").is_some();
52+
if let ExprKind::Unary(_, ref lit) = e.node;
53+
then {
54+
if let ExprKind::Lit(ref inner) = lit.node {
55+
match inner.node {
56+
LitKind::Bool(true) => {
57+
span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
58+
"assert!(true) will be optimized out by the compiler",
59+
"remove it");
60+
},
61+
LitKind::Bool(false) => {
62+
span_help_and_lint(
63+
cx, ASSERTIONS_ON_CONSTANTS, e.span,
64+
"assert!(false) should probably be replaced",
65+
"use panic!() or unreachable!()");
66+
},
67+
_ => (),
68+
}
69+
} else if let Some(bool_const) = constant(cx, cx.tables, lit) {
70+
match bool_const.0 {
71+
Constant::Bool(true) => {
72+
span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
73+
"assert!(const: true) will be optimized out by the compiler",
74+
"remove it");
75+
},
76+
Constant::Bool(false) => {
77+
span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
78+
"assert!(const: false) should probably be replaced",
79+
"use panic!() or unreachable!()");
80+
},
81+
_ => (),
82+
}
83+
}
84+
}
85+
}
86+
}
87+
}

clippy_lints/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ mod utils;
7878
// begin lints modules, do not remove this comment, it’s used in `update_lints`
7979
pub mod approx_const;
8080
pub mod arithmetic;
81+
pub mod assertions_on_constants;
8182
pub mod assign_ops;
8283
pub mod attrs;
8384
pub mod bit_mask;
@@ -477,6 +478,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
477478
reg.register_late_lint_pass(box redundant_clone::RedundantClone);
478479
reg.register_late_lint_pass(box slow_vector_initialization::Pass);
479480
reg.register_late_lint_pass(box types::RefToMut);
481+
reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants);
480482

481483
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
482484
arithmetic::FLOAT_ARITHMETIC,
@@ -554,6 +556,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
554556

555557
reg.register_lint_group("clippy::all", Some("clippy"), vec![
556558
approx_const::APPROX_CONSTANT,
559+
assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
557560
assign_ops::ASSIGN_OP_PATTERN,
558561
assign_ops::MISREFACTORED_ASSIGN_OP,
559562
attrs::DEPRECATED_CFG_ATTR,
@@ -776,6 +779,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
776779
]);
777780

778781
reg.register_lint_group("clippy::style", Some("clippy_style"), vec![
782+
assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
779783
assign_ops::ASSIGN_OP_PATTERN,
780784
attrs::UNKNOWN_CLIPPY_LINTS,
781785
bit_mask::VERBOSE_BIT_MASK,

clippy_lints/src/needless_bool.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
7070
let reduce = |ret, not| {
7171
let mut applicability = Applicability::MachineApplicable;
7272
let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
73-
let snip = if not { !snip } else { snip };
73+
let mut snip = if not { !snip } else { snip };
7474

75-
let mut hint = if ret {
76-
format!("return {}", snip)
77-
} else {
78-
snip.to_string()
79-
};
75+
if ret {
76+
snip = snip.make_return();
77+
}
8078

8179
if parent_node_is_if_expr(&e, &cx) {
82-
hint = format!("{{ {} }}", hint);
80+
snip = snip.blockify()
8381
}
8482

8583
span_lint_and_sugg(
@@ -88,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
8886
e.span,
8987
"this if-then-else expression returns a bool literal",
9088
"you can reduce it to",
91-
hint,
89+
snip.to_string(),
9290
applicability,
9391
);
9492
};

clippy_lints/src/use_self.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@ impl LintPass for UseSelf {
5656
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
5757

5858
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
59+
// path segments only include actual path, no methods or fields
60+
let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span;
61+
// only take path up to the end of last_path_span
62+
let span = path.span.with_hi(last_path_span.hi());
63+
5964
span_lint_and_sugg(
6065
cx,
6166
USE_SELF,
62-
path.span,
67+
span,
6368
"unnecessary structure name repetition",
6469
"use the applicable keyword",
6570
"Self".to_owned(),

clippy_lints/src/utils/mod.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,25 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
6464
/// ```
6565
pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool {
6666
let parent_id = cx.tcx.hir().get_parent(id);
67-
match cx.tcx.hir().body_owner_kind(parent_id) {
68-
hir::BodyOwnerKind::Fn => false,
69-
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(..) => true,
67+
match cx.tcx.hir().get(parent_id) {
68+
Node::Item(&Item {
69+
node: ItemKind::Const(..),
70+
..
71+
})
72+
| Node::TraitItem(&TraitItem {
73+
node: TraitItemKind::Const(..),
74+
..
75+
})
76+
| Node::ImplItem(&ImplItem {
77+
node: ImplItemKind::Const(..),
78+
..
79+
})
80+
| Node::AnonConst(_)
81+
| Node::Item(&Item {
82+
node: ItemKind::Static(..),
83+
..
84+
}) => true,
85+
_ => false,
7086
}
7187
}
7288

clippy_lints/src/utils/sugg.rs

+29
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,17 @@ impl<'a> Sugg<'a> {
206206
make_unop("&mut *", self)
207207
}
208208

209+
/// Convenience method to transform suggestion into a return call
210+
pub fn make_return(self) -> Sugg<'static> {
211+
Sugg::NonParen(Cow::Owned(format!("return {}", self)))
212+
}
213+
214+
/// Convenience method to transform suggestion into a block
215+
/// where the suggestion is a trailing expression
216+
pub fn blockify(self) -> Sugg<'static> {
217+
Sugg::NonParen(Cow::Owned(format!("{{ {} }}", self)))
218+
}
219+
209220
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
210221
/// suggestion.
211222
#[allow(dead_code)]
@@ -578,3 +589,21 @@ impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_error
578589
self.span_suggestion_with_applicability(remove_span, msg, String::new(), applicability);
579590
}
580591
}
592+
593+
#[cfg(test)]
594+
mod test {
595+
use super::Sugg;
596+
use std::borrow::Cow;
597+
598+
const SUGGESTION: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("function_call()"));
599+
600+
#[test]
601+
fn make_return_transform_sugg_into_a_return_call() {
602+
assert_eq!("return function_call()", SUGGESTION.make_return().to_string());
603+
}
604+
605+
#[test]
606+
fn blockify_transforms_sugg_into_a_block() {
607+
assert_eq!("{ function_call() }", SUGGESTION.blockify().to_string());
608+
}
609+
}

tests/ui/assertions_on_constants.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
fn main() {
11+
assert!(true);
12+
assert!(false);
13+
assert!(true, "true message");
14+
assert!(false, "false message");
15+
16+
const B: bool = true;
17+
assert!(B);
18+
19+
const C: bool = false;
20+
assert!(C);
21+
}
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error: assert!(true) will be optimized out by the compiler
2+
--> $DIR/assertions_on_constants.rs:11:5
3+
|
4+
LL | assert!(true);
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::assertions-on-constants` implied by `-D warnings`
8+
= help: remove it
9+
10+
error: assert!(false) should probably be replaced
11+
--> $DIR/assertions_on_constants.rs:12:5
12+
|
13+
LL | assert!(false);
14+
| ^^^^^^^^^^^^^^^
15+
|
16+
= help: use panic!() or unreachable!()
17+
18+
error: assert!(true) will be optimized out by the compiler
19+
--> $DIR/assertions_on_constants.rs:13:5
20+
|
21+
LL | assert!(true, "true message");
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
= help: remove it
25+
26+
error: assert!(false) should probably be replaced
27+
--> $DIR/assertions_on_constants.rs:14:5
28+
|
29+
LL | assert!(false, "false message");
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
= help: use panic!() or unreachable!()
33+
34+
error: assert!(const: true) will be optimized out by the compiler
35+
--> $DIR/assertions_on_constants.rs:17:5
36+
|
37+
LL | assert!(B);
38+
| ^^^^^^^^^^^
39+
|
40+
= help: remove it
41+
42+
error: assert!(const: false) should probably be replaced
43+
--> $DIR/assertions_on_constants.rs:20:5
44+
|
45+
LL | assert!(C);
46+
| ^^^^^^^^^^^
47+
|
48+
= help: use panic!() or unreachable!()
49+
50+
error: aborting due to 6 previous errors
51+

tests/ui/attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::inline_always, clippy::deprecated_semver)]
2-
2+
#![allow(clippy::assertions_on_constants::assertions_on_constants)]
33
#[inline(always)]
44
fn test_attr_lint() {
55
assert!(true)

tests/ui/empty_line_after_outer_attribute.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::empty_line_after_outer_attr)]
2-
2+
#![allow(clippy::assertions_on_constants::assertions_on_constants)]
33
// This should produce a warning
44
#[crate_type = "lib"]
55

tests/ui/panic_unimplemented.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::panic_params, clippy::unimplemented)]
2-
2+
#![allow(clippy::assertions_on_constants::assertions_on_constants)]
33
fn missing() {
44
if true {
55
panic!("{}");

0 commit comments

Comments
 (0)