Skip to content

Commit 99d8509

Browse files
committed
Merge branch 'master' of github.com:rust-lang/rust-clippy
2 parents 98ecce7 + cfdf47e commit 99d8509

File tree

117 files changed

+2882
-1597
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+2882
-1597
lines changed

CHANGELOG.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,38 @@ All notable changes to this project will be documented in this file.
44

55
## Unreleased / In Rust Beta or Nightly
66

7-
[b2601be...master](https://github.com/rust-lang/rust-clippy/compare/b2601be...master)
7+
[1b89724...master](https://github.com/rust-lang/rust-clippy/compare/1b89724...master)
8+
9+
## Rust 1.33 (2019-02-26)
10+
11+
[b2601be...1b89724](https://github.com/rust-lang/rust-clippy/compare/b2601be...1b89724)
12+
13+
* New lints: [`implicit_return`], [`vec_box`], [`cast_ref_to_mut`]
14+
* The `rust-clippy` repository is now part of the `rust-lang` org.
15+
* Rename `stutter` to `module_name_repetitions`
16+
* Merge `new_without_default_derive` into `new_without_default` lint
17+
* Move `large_digit_groups` from `style` group to `pedantic`
18+
* Expand `bool_comparison` to check for `<`, `<=`, `>`, `>=`, and `!=`
19+
comparisons against booleans
20+
* Expand `no_effect` to detect writes to constants such as `A_CONST.field = 2`
21+
* Expand `redundant_clone` to work on struct fields
22+
* Expand `suspicious_else_formatting` to detect `if .. {..} {..}`
23+
* Expand `use_self` to work on tuple structs and also in local macros
24+
* Fix ICE in `result_map_unit_fn` and `option_map_unit_fn`
25+
* Fix false positives in `implicit_return`
26+
* Fix false positives in `use_self`
27+
* Fix false negative in `clone_on_copy`
28+
* Fix false positive in `doc_markdown`
29+
* Fix false positive in `empty_loop`
30+
* Fix false positive in `if_same_then_else`
31+
* Fix false positive in `infinite_iter`
32+
* Fix false positive in `question_mark`
33+
* Fix false positive in `useless_asref`
34+
* Fix false positive in `wildcard_dependencies`
35+
* Fix false positive in `write_with_newline`
36+
* Add suggestion to `explicit_write`
37+
* Improve suggestions for `question_mark` lint
38+
* Fix incorrect suggestion for `get_unwrap`
839

940
## Rust 1.32 (2019-01-17)
1041

@@ -785,6 +816,7 @@ All notable changes to this project will be documented in this file.
785816
[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
786817
[`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg
787818
[`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens
819+
[`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds
788820
[`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy
789821
[`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref
790822
[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g
1111

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

14-
* `clippy::all` (everything that has no false positives)
15-
* `clippy::pedantic` (everything)
16-
* `clippy::nursery` (new lints that aren't quite ready yet)
14+
* `clippy::all` (everything that is on by default: all the categories below except for `nursery`, `pedantic`, and `cargo`)
15+
* **`clippy::correctness`** (code that is just outright wrong or very very useless, causes hard errors by default)
1716
* `clippy::style` (code that should be written in a more idiomatic way)
1817
* `clippy::complexity` (code that does something simple but in a complex way)
1918
* `clippy::perf` (code that can be written in a faster way)
20-
* `clippy::cargo` (checks against the cargo manifest)
21-
* **`clippy::correctness`** (code that is just outright wrong or very very useless)
19+
* `clippy::pedantic` (lints which are rather strict, off by default)
20+
* `clippy::nursery` (new lints that aren't quite ready yet, off by default)
21+
* `clippy::cargo` (checks against the cargo manifest, off by default)
2222

2323
More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
2424

@@ -31,6 +31,8 @@ Only the following of those categories are enabled by default:
3131

3232
Other categories need to be enabled in order for their lints to be executed.
3333

34+
The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also contains "restriction lints", which are for things which are usually not considered "bad", but may be useful to turn on in specific cases. These should be used very selectively, if at all.
35+
3436
Table of contents:
3537

3638
* [Usage instructions](#usage)

ci/base-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ rustup override set nightly
5959
# avoid loop spam and allow cmds with exit status != 0
6060
set +ex
6161

62-
for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/formatting.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do
62+
for file in `find tests -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do
6363
rustfmt ${file} --check
6464
if [ $? -ne 0 ]; then
6565
echo "${file} needs reformatting!"

clippy_dev/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl Lint {
4747
name: name.to_lowercase(),
4848
group: group.to_string(),
4949
desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(),
50-
deprecation: deprecation.map(|d| d.to_string()),
50+
deprecation: deprecation.map(std::string::ToString::to_string),
5151
module: module.to_string(),
5252
}
5353
}
@@ -178,7 +178,7 @@ fn lint_files() -> impl Iterator<Item = walkdir::DirEntry> {
178178
// Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`.
179179
WalkDir::new("../clippy_lints/src")
180180
.into_iter()
181-
.filter_map(|f| f.ok())
181+
.filter_map(std::result::Result::ok)
182182
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
183183
}
184184

clippy_lints/src/assertions_on_constants.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::rustc::hir::{Expr, ExprKind};
33
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
44
use crate::rustc::{declare_tool_lint, lint_array};
55
use crate::syntax::ast::LitKind;
6-
use crate::utils::{is_direct_expn_of, span_help_and_lint};
6+
use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint};
77
use if_chain::if_chain;
88

99
/// **What it does:** Check to call assert!(true/false)
@@ -43,7 +43,9 @@ impl LintPass for AssertionsOnConstants {
4343
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
4444
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
4545
if_chain! {
46-
if is_direct_expn_of(e.span, "assert").is_some();
46+
if let Some(assert_span) = is_direct_expn_of(e.span, "assert");
47+
if !in_macro(assert_span)
48+
|| is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| !in_macro(span));
4749
if let ExprKind::Unary(_, ref lit) = e.node;
4850
then {
4951
if let ExprKind::Lit(ref inner) = lit.node {

clippy_lints/src/assign_ops.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
66
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
77
use rustc::{declare_tool_lint, lint_array};
88
use rustc_errors::Applicability;
9-
use syntax::ast;
109

1110
/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
1211
/// patterns.
@@ -140,12 +139,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
140139
return; // useless if the trait doesn't exist
141140
};
142141
// check that we are not inside an `impl AssignOp` of this exact operation
143-
let parent_fn = cx.tcx.hir().get_parent(e.id);
144-
let parent_impl = cx.tcx.hir().get_parent(parent_fn);
142+
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
143+
let parent_impl = cx.tcx.hir().get_parent_item(parent_fn);
145144
// the crate node is the only one that is not in the map
146145
if_chain! {
147-
if parent_impl != ast::CRATE_NODE_ID;
148-
if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
146+
if parent_impl != hir::CRATE_HIR_ID;
147+
if let hir::Node::Item(item) = cx.tcx.hir().get_by_hir_id(parent_impl);
149148
if let hir::ItemKind::Impl(_, _, _, _, Some(trait_ref), _, _) =
150149
&item.node;
151150
if trait_ref.path.def.def_id() == trait_id;

clippy_lints/src/attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
326326
lint.span,
327327
&format!("unknown clippy lint: clippy::{}", name),
328328
|db| {
329-
if name.as_str().chars().any(|c| c.is_uppercase()) {
329+
if name.as_str().chars().any(char::is_uppercase) {
330330
let name_lower = name.as_str().to_lowercase();
331331
match lint_store.check_lint_name(
332332
&name_lower,

clippy_lints/src/booleans.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
77
use rustc::{declare_tool_lint, lint_array};
88
use rustc_data_structures::thin_vec::ThinVec;
99
use rustc_errors::Applicability;
10-
use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID};
10+
use syntax::ast::LitKind;
1111
use syntax::source_map::{dummy_spanned, Span, DUMMY_SP};
1212

1313
/// **What it does:** Checks for boolean expressions that can be written more
@@ -72,7 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool {
7272
_: &'tcx FnDecl,
7373
body: &'tcx Body,
7474
_: Span,
75-
_: NodeId,
75+
_: HirId,
7676
) {
7777
NonminimalBoolVisitor { cx }.visit_body(body)
7878
}
@@ -132,7 +132,6 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
132132
}
133133

134134
let mk_expr = |op| Expr {
135-
id: DUMMY_NODE_ID,
136135
hir_id: DUMMY_HIR_ID,
137136
span: DUMMY_SP,
138137
attrs: ThinVec::new(),

clippy_lints/src/cargo_common_metadata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn is_empty_str(value: &Option<String>) -> bool {
5353

5454
fn is_empty_vec(value: &[String]) -> bool {
5555
// This works because empty iterators return true
56-
value.iter().all(|v| v.is_empty())
56+
value.iter().all(std::string::String::is_empty)
5757
}
5858

5959
pub struct Pass;

clippy_lints/src/consts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use if_chain::if_chain;
55
use rustc::hir::def::Def;
66
use rustc::hir::*;
77
use rustc::lint::LateContext;
8-
use rustc::ty::subst::{Subst, Substs};
8+
use rustc::ty::subst::{Subst, SubstsRef};
99
use rustc::ty::{self, Instance, Ty, TyCtxt};
1010
use rustc::{bug, span_bug};
1111
use rustc_data_structures::sync::Lrc;
@@ -209,7 +209,7 @@ pub struct ConstEvalLateContext<'a, 'tcx: 'a> {
209209
tables: &'a ty::TypeckTables<'tcx>,
210210
param_env: ty::ParamEnv<'tcx>,
211211
needed_resolution: bool,
212-
substs: &'tcx Substs<'tcx>,
212+
substs: SubstsRef<'tcx>,
213213
}
214214

215215
impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {

clippy_lints/src/copies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
125125
..
126126
}) = get_parent_expr(cx, expr)
127127
{
128-
if else_expr.id == expr.id {
128+
if else_expr.hir_id == expr.hir_id {
129129
return;
130130
}
131131
}

clippy_lints/src/cyclomatic_complexity.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc::hir::*;
66
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
77
use rustc::ty;
88
use rustc::{declare_tool_lint, lint_array};
9-
use syntax::ast::{Attribute, NodeId};
9+
use syntax::ast::Attribute;
1010
use syntax::source_map::Span;
1111

1212
use crate::utils::{in_macro, is_allowed, match_type, paths, span_help_and_lint, LimitStack};
@@ -78,7 +78,7 @@ impl CyclomaticComplexity {
7878
returns,
7979
..
8080
} = helper;
81-
let ret_ty = cx.tables.node_id_to_type(expr.hir_id);
81+
let ret_ty = cx.tables.node_type(expr.hir_id);
8282
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
8383
returns
8484
} else {
@@ -94,7 +94,7 @@ impl CyclomaticComplexity {
9494
short_circuits,
9595
ret_adjust,
9696
span,
97-
body.id().node_id,
97+
body.id().hir_id,
9898
);
9999
} else {
100100
let mut rust_cc = cc + divergence - match_arms - short_circuits;
@@ -123,9 +123,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity {
123123
_: &'tcx FnDecl,
124124
body: &'tcx Body,
125125
span: Span,
126-
node_id: NodeId,
126+
hir_id: HirId,
127127
) {
128-
let def_id = cx.tcx.hir().local_def_id(node_id);
128+
let def_id = cx.tcx.hir().local_def_id_from_hir_id(hir_id);
129129
if !cx.tcx.has_attr(def_id, "test") {
130130
self.check(cx, body, span);
131131
}
@@ -159,7 +159,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> {
159159
},
160160
ExprKind::Call(ref callee, _) => {
161161
walk_expr(self, e);
162-
let ty = self.cx.tables.node_id_to_type(callee.hir_id);
162+
let ty = self.cx.tables.node_type(callee.hir_id);
163163
match ty.sty {
164164
ty::FnDef(..) | ty::FnPtr(_) => {
165165
let sig = ty.fn_sig(self.cx.tcx);
@@ -197,7 +197,7 @@ fn report_cc_bug(
197197
shorts: u64,
198198
returns: u64,
199199
span: Span,
200-
_: NodeId,
200+
_: HirId,
201201
) {
202202
span_bug!(
203203
span,
@@ -220,7 +220,7 @@ fn report_cc_bug(
220220
shorts: u64,
221221
returns: u64,
222222
span: Span,
223-
id: NodeId,
223+
id: HirId,
224224
) {
225225
if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) {
226226
cx.sess().span_note_without_error(

clippy_lints/src/default_trait_access.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
4545
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
4646
if_chain! {
4747
if let ExprKind::Call(ref path, ..) = expr.node;
48-
if !any_parent_is_automatically_derived(cx.tcx, expr.id);
48+
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
4949
if let ExprKind::Path(ref qpath) = path.node;
5050
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
5151
if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD);

clippy_lints/src/drop_bounds.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use crate::utils::{match_def_path, paths, span_lint};
2+
use if_chain::if_chain;
3+
use rustc::hir::*;
4+
use rustc::lint::{LateLintPass, LintArray, LintPass};
5+
use rustc::{declare_tool_lint, lint_array};
6+
7+
/// **What it does:** Checks for generics with `std::ops::Drop` as bounds.
8+
///
9+
/// **Why is this bad?** `Drop` bounds do not really accomplish anything.
10+
/// A type may have compiler-generated drop glue without implementing the
11+
/// `Drop` trait itself. The `Drop` trait also only has one method,
12+
/// `Drop::drop`, and that function is by fiat not callable in user code.
13+
/// So there is really no use case for using `Drop` in trait bounds.
14+
///
15+
/// The most likely use case of a drop bound is to distinguish between types
16+
/// that have destructors and types that don't. Combined with specialization,
17+
/// a naive coder would write an implementation that assumed a type could be
18+
/// trivially dropped, then write a specialization for `T: Drop` that actually
19+
/// calls the destructor. Except that doing so is not correct; String, for
20+
/// example, doesn't actually implement Drop, but because String contains a
21+
/// Vec, assuming it can be trivially dropped will leak memory.
22+
///
23+
/// **Known problems:** None.
24+
///
25+
/// **Example:**
26+
/// ```rust
27+
/// fn foo<T: Drop>() {}
28+
/// ```
29+
declare_clippy_lint! {
30+
pub DROP_BOUNDS,
31+
correctness,
32+
"Bounds of the form `T: Drop` are useless"
33+
}
34+
35+
const DROP_BOUNDS_SUMMARY: &str = "Bounds of the form `T: Drop` are useless. \
36+
Use `std::mem::needs_drop` to detect if a type has drop glue.";
37+
38+
pub struct Pass;
39+
40+
impl LintPass for Pass {
41+
fn get_lints(&self) -> LintArray {
42+
lint_array!(DROP_BOUNDS)
43+
}
44+
45+
fn name(&self) -> &'static str {
46+
"DropBounds"
47+
}
48+
}
49+
50+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
51+
fn check_generic_param(&mut self, cx: &rustc::lint::LateContext<'a, 'tcx>, p: &'tcx GenericParam) {
52+
for bound in &p.bounds {
53+
lint_bound(cx, bound);
54+
}
55+
}
56+
fn check_where_predicate(&mut self, cx: &rustc::lint::LateContext<'a, 'tcx>, p: &'tcx WherePredicate) {
57+
if let WherePredicate::BoundPredicate(WhereBoundPredicate { bounds, .. }) = p {
58+
for bound in bounds {
59+
lint_bound(cx, bound);
60+
}
61+
}
62+
}
63+
}
64+
65+
fn lint_bound<'a, 'tcx>(cx: &rustc::lint::LateContext<'a, 'tcx>, bound: &'tcx GenericBound) {
66+
if_chain! {
67+
if let GenericBound::Trait(t, _) = bound;
68+
if let Some(def_id) = t.trait_ref.path.def.opt_def_id();
69+
if match_def_path(cx.tcx, def_id, &paths::DROP_TRAIT);
70+
then {
71+
span_lint(
72+
cx,
73+
DROP_BOUNDS,
74+
t.span,
75+
DROP_BOUNDS_SUMMARY
76+
);
77+
}
78+
}
79+
}

clippy_lints/src/enum_clike.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc::hir::*;
77
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
88
use rustc::mir::interpret::GlobalId;
99
use rustc::ty;
10-
use rustc::ty::subst::Substs;
10+
use rustc::ty::subst::InternalSubsts;
1111
use rustc::ty::util::IntTypeExt;
1212
use rustc::{declare_tool_lint, lint_array};
1313
use syntax::ast::{IntTy, UintTy};
@@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
5858
if let Some(ref anon_const) = variant.disr_expr {
5959
let param_env = ty::ParamEnv::empty();
6060
let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body);
61-
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
61+
let substs = InternalSubsts::identity_for_item(cx.tcx.global_tcx(), def_id);
6262
let instance = ty::Instance::new(def_id, substs);
6363
let c_id = GlobalId {
6464
instance,

0 commit comments

Comments
 (0)