Skip to content

Commit f239f7d

Browse files
Merge branch 'master' of https://github.com/rust-lang/rust-clippy into cast-ref-to-mut
2 parents 6e12403 + 0a6593c commit f239f7d

29 files changed

+508
-255
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,7 @@ All notable changes to this project will be documented in this file.
815815
[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
816816
[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
817817
[`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
818+
[`random_state`]: https://rust-lang.github.io/rust-clippy/master/index.html#random_state
818819
[`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one
819820
[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
820821
[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero

README.md

+2-2
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

@@ -79,7 +79,7 @@ To have cargo compile your crate with Clippy without Clippy installation
7979
in your code, you can use:
8080

8181
```terminal
82-
RUSTFLAGS=--sysroot=`rustc --print sysroot` cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
82+
cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
8383
```
8484

8585
*[Note](https://github.com/rust-lang/rust-clippy/wiki#a-word-of-warning):*

clippy_lints/src/blacklisted_name.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::utils::span_lint;
1111
use rustc::hir::*;
1212
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
1313
use rustc::{declare_tool_lint, lint_array};
14+
use rustc_data_structures::fx::FxHashSet;
1415

1516
/// **What it does:** Checks for usage of blacklisted names for variables, such
1617
/// as `foo`.
@@ -32,11 +33,11 @@ declare_clippy_lint! {
3233

3334
#[derive(Clone, Debug)]
3435
pub struct BlackListedName {
35-
blacklist: Vec<String>,
36+
blacklist: FxHashSet<String>,
3637
}
3738

3839
impl BlackListedName {
39-
pub fn new(blacklist: Vec<String>) -> Self {
40+
pub fn new(blacklist: FxHashSet<String>) -> Self {
4041
Self { blacklist }
4142
}
4243
}
@@ -50,7 +51,7 @@ impl LintPass for BlackListedName {
5051
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName {
5152
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
5253
if let PatKind::Binding(_, _, ident, _) = pat.node {
53-
if self.blacklist.iter().any(|s| ident.name == *s) {
54+
if self.blacklist.contains(&ident.name.to_string()) {
5455
span_lint(
5556
cx,
5657
BLACKLISTED_NAME,

clippy_lints/src/doc.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use itertools::Itertools;
1212
use pulldown_cmark;
1313
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
1414
use rustc::{declare_tool_lint, lint_array};
15+
use rustc_data_structures::fx::FxHashSet;
1516
use syntax::ast;
1617
use syntax::source_map::{BytePos, Span};
1718
use syntax_pos::Pos;
@@ -43,11 +44,11 @@ declare_clippy_lint! {
4344

4445
#[derive(Clone)]
4546
pub struct Doc {
46-
valid_idents: Vec<String>,
47+
valid_idents: FxHashSet<String>,
4748
}
4849

4950
impl Doc {
50-
pub fn new(valid_idents: Vec<String>) -> Self {
51+
pub fn new(valid_idents: FxHashSet<String>) -> Self {
5152
Self { valid_idents }
5253
}
5354
}
@@ -144,7 +145,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(
144145
panic!("not a doc-comment: {}", comment);
145146
}
146147

147-
pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &'a [ast::Attribute]) {
148+
pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [ast::Attribute]) {
148149
let mut doc = String::new();
149150
let mut spans = vec![];
150151

@@ -192,7 +193,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &'
192193

193194
fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
194195
cx: &EarlyContext<'_>,
195-
valid_idents: &[String],
196+
valid_idents: &FxHashSet<String>,
196197
docs: Events,
197198
spans: &[(usize, Span)],
198199
) {
@@ -237,14 +238,14 @@ fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
237238
}
238239
}
239240

240-
fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) {
241+
fn check_text(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) {
241242
for word in text.split(|c: char| c.is_whitespace() || c == '\'') {
242243
// Trim punctuation as in `some comment (see foo::bar).`
243244
// ^^
244245
// Or even as in `_foo bar_` which is emphasized.
245246
let word = word.trim_matches(|c: char| !c.is_alphanumeric());
246247

247-
if valid_idents.iter().any(|i| i == word) {
248+
if valid_idents.contains(word) {
248249
continue;
249250
}
250251

clippy_lints/src/infinite_iter.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10-
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint};
10+
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
1111
use rustc::hir::*;
1212
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
1313
use rustc::{declare_tool_lint, lint_array};
@@ -200,7 +200,6 @@ static POSSIBLY_COMPLETING_METHODS: &[(&str, usize)] = &[
200200
/// their iterators
201201
static COMPLETING_METHODS: &[(&str, usize)] = &[
202202
("count", 1),
203-
("collect", 1),
204203
("fold", 3),
205204
("for_each", 2),
206205
("partition", 2),
@@ -214,6 +213,18 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[
214213
("product", 1),
215214
];
216215

216+
/// the paths of types that are known to be infinitely allocating
217+
static INFINITE_COLLECTORS: &[&[&str]] = &[
218+
&paths::BINARY_HEAP,
219+
&paths::BTREEMAP,
220+
&paths::BTREESET,
221+
&paths::HASHMAP,
222+
&paths::HASHSET,
223+
&paths::LINKED_LIST,
224+
&paths::VEC,
225+
&paths::VEC_DEQUE,
226+
];
227+
217228
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
218229
match expr.node {
219230
ExprKind::MethodCall(ref method, _, ref args) => {
@@ -233,6 +244,11 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
233244
if not_double_ended {
234245
return is_infinite(cx, &args[0]);
235246
}
247+
} else if method.ident.name == "collect" {
248+
let ty = cx.tables.expr_ty(expr);
249+
if INFINITE_COLLECTORS.iter().any(|path| match_type(cx, ty, path)) {
250+
return is_infinite(cx, &args[0]);
251+
}
236252
}
237253
},
238254
ExprKind::Binary(op, ref l, ref r) => {

clippy_lints/src/lib.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ pub mod precedence;
180180
pub mod ptr;
181181
pub mod ptr_offset_with_cast;
182182
pub mod question_mark;
183+
pub mod random_state;
183184
pub mod ranges;
184185
pub mod redundant_clone;
185186
pub mod redundant_field_names;
@@ -423,9 +424,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
423424
reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional);
424425
reg.register_late_lint_pass(box unused_label::UnusedLabel);
425426
reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default());
426-
reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone()));
427+
reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(
428+
conf.blacklisted_names.iter().cloned().collect()
429+
));
427430
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
428-
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone()));
431+
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect()));
429432
reg.register_late_lint_pass(box neg_multiply::NegMultiply);
430433
reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
431434
reg.register_late_lint_pass(box mem_discriminant::MemDiscriminant);
@@ -484,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
484487
reg.register_late_lint_pass(box ptr_offset_with_cast::Pass);
485488
reg.register_late_lint_pass(box redundant_clone::RedundantClone);
486489
reg.register_late_lint_pass(box slow_vector_initialization::Pass);
490+
reg.register_late_lint_pass(box random_state::Pass);
487491
reg.register_late_lint_pass(box types::RefToMut);
488492

489493
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
@@ -1024,6 +1028,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
10241028
fallible_impl_from::FALLIBLE_IMPL_FROM,
10251029
mutex_atomic::MUTEX_INTEGER,
10261030
needless_borrow::NEEDLESS_BORROW,
1031+
random_state::RANDOM_STATE,
10271032
redundant_clone::REDUNDANT_CLONE,
10281033
types::CAST_REF_TO_MUT,
10291034
unwrap::PANICKING_UNWRAP,

clippy_lints/src/random_state.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::utils::{match_type, paths, span_lint};
2+
use rustc::hir::Ty;
3+
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
4+
use rustc::ty::subst::UnpackedKind;
5+
use rustc::ty::TyKind;
6+
use rustc::{declare_tool_lint, lint_array};
7+
8+
/// **What it does:** Checks for usage of `RandomState`
9+
///
10+
/// **Why is this bad?** Some applications don't need collision prevention
11+
/// which lowers the performance.
12+
///
13+
/// **Known problems:** None.
14+
///
15+
/// **Example:**
16+
/// ```rust
17+
/// fn x() {
18+
/// let mut map = std::collections::HashMap::new();
19+
/// map.insert(3, 4);
20+
/// }
21+
/// ```
22+
declare_clippy_lint! {
23+
pub RANDOM_STATE,
24+
nursery,
25+
"use of RandomState"
26+
}
27+
28+
pub struct Pass;
29+
30+
impl LintPass for Pass {
31+
fn get_lints(&self) -> LintArray {
32+
lint_array!(RANDOM_STATE)
33+
}
34+
}
35+
36+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
37+
fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &Ty) {
38+
if let Some(tys) = cx.tables.node_id_to_type_opt(ty.hir_id) {
39+
if let TyKind::Adt(_, substs) = tys.sty {
40+
for subst in substs {
41+
if let UnpackedKind::Type(build_hasher) = subst.unpack() {
42+
if match_type(cx, build_hasher, &paths::RANDOM_STATE) {
43+
span_lint(cx, RANDOM_STATE, ty.span, "usage of RandomState");
44+
}
45+
}
46+
}
47+
}
48+
}
49+
}
50+
}

clippy_lints/src/utils/hir_utils.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
5454
match (&left.node, &right.node) {
5555
(&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => {
5656
if let (&DeclKind::Local(ref l), &DeclKind::Local(ref r)) = (&l.node, &r.node) {
57-
both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
57+
self.eq_pat(&l.pat, &r.pat)
58+
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
59+
&& both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
5860
} else {
5961
false
6062
}

clippy_lints/src/utils/mod.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
6262
rhs.ctxt() != lhs.ctxt()
6363
}
6464

65+
/// Returns `true` if the given `NodeId` is inside a constant context
66+
///
67+
/// # Example
68+
///
69+
/// ```rust,ignore
70+
/// if in_constant(cx, expr.id) {
71+
/// // Do something
72+
/// }
73+
/// ```
6574
pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool {
6675
let parent_id = cx.tcx.hir().get_parent(id);
6776
match cx.tcx.hir().body_owner_kind(parent_id) {
@@ -377,6 +386,9 @@ pub fn contains_name(name: Name, expr: &Expr) -> bool {
377386

378387
/// Convert a span to a code snippet if available, otherwise use default.
379388
///
389+
/// This is useful if you want to provide suggestions for your lint or more generally, if you want
390+
/// to convert a given `Span` to a `str`.
391+
///
380392
/// # Example
381393
/// ```rust,ignore
382394
/// snippet(cx, expr.span, "..")
@@ -430,7 +442,7 @@ pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String>
430442
///
431443
/// # Example
432444
/// ```rust,ignore
433-
/// snippet(cx, expr.span, "..")
445+
/// snippet_block(cx, expr.span, "..")
434446
/// ```
435447
pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
436448
let snip = snippet(cx, span, default);
@@ -741,6 +753,13 @@ pub fn is_integer_literal(expr: &Expr, value: u128) -> bool {
741753
false
742754
}
743755

756+
/// Returns `true` if the given `Expr` has been coerced before.
757+
///
758+
/// Examples of coercions can be found in the Nomicon at
759+
/// <https://doc.rust-lang.org/nomicon/coercions.html>.
760+
///
761+
/// See `rustc::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
762+
/// information on adjustments and coercions.
744763
pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
745764
cx.tables.adjustments().get(e.hir_id).is_some()
746765
}

clippy_lints/src/utils/paths.rs

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"];
7373
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
7474
pub const PTR_NULL: [&str; 2] = ["ptr", "null"];
7575
pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"];
76+
pub const RANDOM_STATE: [&str; 5] = ["std", "collections", "hash", "map", "RandomState"];
7677
pub const RANGE: [&str; 3] = ["core", "ops", "Range"];
7778
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
7879
pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"];

rustc_tools_util/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rustc_tools_util"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
authors = ["Matthias Krüger <[email protected]>"]
55
description = "small helper to generate version information for git packages"
66
repository = "https://github.com/rust-lang/rust-clippy"

rustc_tools_util/src/lib.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,17 @@ pub struct VersionInfo {
4646

4747
impl std::fmt::Display for VersionInfo {
4848
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49-
if self.commit_hash.is_some() {
49+
let hash = self.commit_hash.clone().unwrap_or_default();
50+
let hash_trimmed = hash.trim();
51+
52+
let date = self.commit_date.clone().unwrap_or_default();
53+
let date_trimmed = date.trim();
54+
55+
if (hash_trimmed.len() + date_trimmed.len()) > 0 {
5056
write!(
5157
f,
5258
"{} {}.{}.{} ({} {})",
53-
self.crate_name,
54-
self.major,
55-
self.minor,
56-
self.patch,
57-
self.commit_hash.clone().unwrap_or_default().trim(),
58-
self.commit_date.clone().unwrap_or_default().trim(),
59+
self.crate_name, self.major, self.minor, self.patch, hash_trimmed, date_trimmed,
5960
)?;
6061
} else {
6162
write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?;
@@ -121,7 +122,7 @@ mod test {
121122
let vi = get_version_info!();
122123
assert_eq!(vi.major, 0);
123124
assert_eq!(vi.minor, 1);
124-
assert_eq!(vi.patch, 0);
125+
assert_eq!(vi.patch, 1);
125126
assert_eq!(vi.crate_name, "rustc_tools_util");
126127
// hard to make positive tests for these since they will always change
127128
assert!(vi.commit_hash.is_none());
@@ -131,7 +132,7 @@ mod test {
131132
#[test]
132133
fn test_display_local() {
133134
let vi = get_version_info!();
134-
assert_eq!(vi.to_string(), "rustc_tools_util 0.1.0");
135+
assert_eq!(vi.to_string(), "rustc_tools_util 0.1.1");
135136
}
136137

137138
#[test]
@@ -140,7 +141,7 @@ mod test {
140141
let s = format!("{:?}", vi);
141142
assert_eq!(
142143
s,
143-
"VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 0 }"
144+
"VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 1 }"
144145
);
145146
}
146147

tests/ui/builtin-type-shadow.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
1212
LL | fn foo<u32>(a: u32) -> u32 {
1313
| --- expected `u32` because of return type
1414
LL | 42
15-
| ^^ expected type parameter, found integral variable
15+
| ^^ expected type parameter, found integer
1616
|
1717
= note: expected type `u32`
1818
found type `{integer}`

0 commit comments

Comments
 (0)